Usando `textField: shouldChangeCharactersInRange:`, ¿cómo obtengo el texto que incluye el carácter escrito actual?

116

Estoy usando el siguiente código para intentar que textField2el contenido de texto se actualice para que coincida textField1cada vez que el usuario escribe textField1.

- (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange: (NSRange)range replacementString: (NSString *)string {    
  if (theTextField == textField1){    
     [textField2 setText:[textField1 text]];    
  }
}

Sin embargo, el resultado que observo es que ...

textField2 es "12", cuando textField1 es "123"

textField2 es "123", cuando textField1 es "1234"

... cuando lo que quiero es:

textField2 es "123", cuando textField1 es "123"

textField2 es "1234", cuando textField1 es "1234"

¿Qué estoy haciendo mal?

user265961
fuente
8
Solo un recordatorio de que es asombrosamente más fácil usar siempre el evento "Editing Changed" ... simplemente arrástrelo en IB a una función que cree.
Fattie
Tenga en cuenta que el evento de edición modificada no captura ningún evento de cambio de texto generado mediante programación, por ejemplo, autocorrección / autocompletado / reemplazo de texto.
calzar el

Respuestas:

272

-shouldChangeCharactersInRangese llama antes de que el campo de texto cambie su texto, por eso está obteniendo un valor de texto antiguo. Para obtener el texto después de la actualización, use:

[textField2 setText:[textField1.text stringByReplacingCharactersInRange:range withString:string]];
Vladimir
fuente
15
Esto casi funcionó para mí. Si escribí un carácter, esto funcionó. Si presioné el botón Eliminar, eliminaría dos caracteres. Para mí, la siguiente sugerencia funcionó: stackoverflow.com/questions/388237/… Básicamente, arrastre y suelte desde UITextField a su código (para crear una función), luego haga clic con el botón derecho en su TextField y arrastre 'n' pase del círculo de "Edición modificada" a su nueva función. (Suspiro. A veces echo de menos Visual Studio ...)
Mike Gledhill
También siento que esta es una respuesta válida, pero no LA respuesta. La mejor manera de lograr lo que quieres fue respondida por @tomute
Pedro Borges
5
O textFiel.text = (textFiel.text como NSString) .stringByReplacingCharactersInRange (range, withString: string) en Swift
Máx.
@MikeGledhill Puede hacer lo mismo programáticamente:[textField addTarget:self action:@selector(textFieldEditingChanged:) forControlEvents:UIControlEventEditingChanged]
Steve Moser
52
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString * searchStr = [textField.text stringByReplacingCharactersInRange:range withString:string];

    NSLog(@"%@",searchStr);
    return YES;
}
btmanikandan
fuente
40

Swift 3

Según la respuesta aceptada, lo siguiente debería funcionar en Swift 3 :

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    let newString = NSString(string: textField.text!).replacingCharacters(in: range, with: string)

    return true
}

Nota

Ambos Stringy NSStringtienen métodos llamados replacingCharacters:inRange:withString. Sin embargo, como se esperaba, el primero espera una instancia de Range, mientras que el segundo espera una instancia de NSRange. El textFieldmétodo delegado usa una NSRangeinstancia, de ahí el uso de NSStringen este caso.

focorner
fuente
replacingCharactersdebería serstringByReplacingCharactersInRange
Alan Scarpa
1
@Alan_s Copié este fragmento directamente de mi proyecto Xcode y estaba funcionando bien. ¿Está utilizando Xcode 8.1 con destino a iOS 10.1?
focorner
25

En lugar de utilizar UITextFieldDelegate, intente utilizar el evento "Editing Changed" de UITextField.

Silenciar
fuente
13

En Swift (4), sin NSString(Swift puro):

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if let textFieldString = textField.text, let swtRange = Range(range, in: textFieldString) {

        let fullString = textFieldString.replacingCharacters(in: swtRange, with: string)

        print("FullString: \(fullString)")
    }

    return true
}

Como extensión:

extension UITextField {

    func fullTextWith(range: NSRange, replacementString: String) -> String? {

        if let fullSearchString = self.text, let swtRange = Range(range, in: fullSearchString) {

            return fullSearchString.replacingCharacters(in: swtRange, with: replacementString)
        }

        return nil
    }
}

// Usage:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if let textFieldString = textField.fullTextWith(range: range, replacementString: string) {
        print("FullString: \(textFieldString)")
    }

    return true
}
bauerMusic
fuente
8

Versión rápida para ello:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

    if string == " " {
        return false
    }

    let userEnteredString = textField.text

    var newString = (userEnteredString! as NSString).stringByReplacingCharactersInRange(range, withString: string) as NSString

    print(newString)

    return true
}
ioopl
fuente
5

Este es el código que necesitas

if ([textField isEqual:self.textField1])
  textField2.text = [textField1.text stringByReplacingCharactersInRange:range withString:string];
Deepak Danduprolu
fuente
1

usar guardia

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        guard case let textFieldString as NSString = textField.text where
            textFieldString.stringByReplacingCharactersInRange(range, withString: string).length <= maxLength else {
                return false
        }
        return true
    }
ober
fuente
0

Mi solución es usar UITextFieldTextDidChangeNotification.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(copyText:) name:UITextFieldTextDidChangeNotification object:nil];

No olvide llamar [[NSNotificationCenter defaultCenter] removeObserver:self];al deallocmétodo.

Boweidmann
fuente