UITextField evento de cambio de texto

¿Cómo puedo detectar cualquier cambio de texto en un campo de texto? El método delegado shouldChangeCharactersInRange funciona para algo, pero no shouldChangeCharactersInRange mi necesidad exactamente. Desde que hasta que devuelve SÍ, los textos del campo de texto no están disponibles para otros métodos de observación.

por ejemplo, en mi código calculateAndUpdateTextFields no obtuvo el texto actualizado, el usuario lo ha tipeado.

¿Hay alguna manera de obtener algo como el controlador de eventos textChanged Java?

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if (textField.tag == kTextFieldTagSubtotal || textField.tag == kTextFieldTagSubtotalDecimal || textField.tag == kTextFieldTagShipping || textField.tag == kTextFieldTagShippingDecimal) { [self calculateAndUpdateTextFields]; } return YES; } 

De la forma correcta de hacer el cambio de texto de uitextfield, llame de nuevo :

Capturo los caracteres enviados a un control UITextField algo como esto:

 // Add a "textFieldDidChange" notification method to the text field control. [textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; 

Luego, en el método textFieldDidChange: puede examinar el contenido de textField y volver a cargar la vista de tabla según sea necesario.

Puede usar eso y poner calculateAndUpdateTextFields como su selector .

La respuesta de XenElement es perfecta.

Lo anterior también se puede hacer en el constructor de interfaz haciendo clic derecho en el UITextField y arrastrando el evento de envío “Editing Changed” a su unidad de subclase.

Evento de cambio de UITextField

para configurar el oyente del evento:

 [self.textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; 

para escuchar realmente:

 - (void)textFieldDidChange:(UITextField *)textField { NSLog(@"text changed: %@", textField.text); } 

Rápido:

 yourTextfield.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged) 

Luego, implemente la función de callback:

 @objc func textFieldDidChange(textField: UITextField){ print("Text changed") } 

Como se indica aquí: evento de cambio de texto de UITextField , parece que a partir de iOS 6 (comprobados iOS 6.0 y 6.1) no es posible detectar completamente los cambios en los objetos UITextField simplemente observando el UITextFieldTextDidChangeNotification .

Parece que ahora solo se rastrean los cambios realizados directamente por el teclado iOS incorporado. Esto significa que si cambia su objeto UITextField simplemente invocando algo como esto: myUITextField.text = @"any_text" , no recibirá ninguna notificación sobre ningún cambio.

No sé si esto es un error o está destinado. Parece un error ya que no encontré ninguna explicación razonable en la documentación. Esto también se indica aquí: evento de cambio de texto UITextField .

Mi “solución” para esto es publicar una notificación por mí mismo por cada cambio que realice en mi UITextField (si ese cambio se realiza sin usar el teclado iOS incorporado). Algo como esto:

 myUITextField.text = @"I'm_updating_my_UITextField_directly_in_code"; NSNotification *myTextFieldUpdateNotification = [NSNotification notificationWithName:UITextFieldTextDidChangeNotification object:myUITextField]; [NSNotificationCenter.defaultCenter postNotification:myTextFieldUpdateNotification]; 

De esta manera, usted está 100% seguro de que recibirá la misma notificación cuando cambie la propiedad .text de su objeto UITextField , ya sea cuando la actualice “manualmente” en su código o mediante el teclado iOS incorporado.

Es importante considerar que, dado que este no es un comportamiento documentado, este enfoque puede generar 2 notificaciones recibidas por el mismo cambio en su objeto UITextField . Dependiendo de sus necesidades (lo que realmente hace cuando su UITextField.text cambia) esto podría ser un inconveniente para usted.

Un enfoque ligeramente diferente sería publicar una notificación personalizada (esto es, con un nombre personalizado que no sea UITextFieldTextDidChangeNotification ) si realmente necesita saber si la notificación fue suya o “iOS-made”.

EDITAR:

Acabo de encontrar un enfoque diferente que creo que podría ser mejor:

Esto implica la característica de Observación de valores-clave (KVO) de Objective-C ( http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid / 10000177-BCICJDHA ).

Básicamente, usted se registra como observador de una propiedad y si esta propiedad cambia, se le notificará al respecto. El “principio” es bastante similar a cómo funciona NSNotificationCenter , siendo la ventaja principal que este enfoque funciona automáticamente también a partir de iOS 6 (sin ningún ajuste especial como tener que publicar notificaciones manualmente).

Para nuestro UITextField -scenario, esto funciona bien si agrega este código a, por ejemplo, su UIViewController que contiene el campo de texto:

 static void *myContext = &myContext; - (void)viewDidLoad { [super viewDidLoad]; //Observing changes to myUITextField.text: [myUITextField addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:myContext]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if(context == myContext) { //Here you get notified every time myUITextField's "text" property is updated NSLog(@"New value: %@ - Old value: %@", [change objectForKey:NSKeyValueChangeNewKey], [change objectForKey:NSKeyValueChangeOldKey]); } else [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } 

Gracias a esta respuesta sobre la gestión del “contexto”: https://stackoverflow.com/a/12097161/2078512

Nota: Parece que mientras está en el proceso de editar un UITextField con el teclado iOS incorporado, la propiedad “texto” del campo de texto no se actualiza con cada nueva letra escrita / eliminada. En su lugar, el objeto de campo de texto se actualiza “en conjunto” después de que usted renuncie al estado del primer respondedor del campo de texto.

Podemos configurarlo fácilmente desde Storyboard , CTRL arrastrar la @IBAction y cambiar el evento de la siguiente manera:

enter image description here

Aquí en versión rápida para lo mismo.

 textField.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged) func textFieldDidChange(textField: UITextField) { } 

Gracias

Resolví el problema cambiando el comportamiento de shouldChangeChractersInRange. Si devuelve NO, iOS no aplicará los cambios internamente, sino que tendrá la oportunidad de cambiarlo manualmente y realizar cualquier acción después de los cambios.

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { //Replace the string manually in the textbox textField.text = [textField.text stringByReplacingCharactersInRange:range withString:string]; //perform any logic here now that you are sure the textbox text has changed [self didChangeTextInTextField:textField]; return NO; //this make iOS not to perform any action } 

Versión Swift probada:

 //Somewhere in your UIViewController, like viewDidLoad(){ ... } self.textField.addTarget( self, action: #selector(SearchViewController.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingChanged ) 

Parámetros explicados:

 self.textField //-> A UITextField defined somewhere in your UIViewController self //-> UIViewController .textFieldDidChange(_:) //-> Can be named anyway you like, as long as it is defined in your UIViewController 

A continuación, agregue el método que creó anteriormente en su UIViewController :

 //Gets called everytime the text changes in the textfield. func textFieldDidChange(textField: UITextField){ print("Text changed: " + textField.text!) } 

Para Swift 3.0:

 let textField = UITextField() textField.addTarget( nil, action: #selector(MyClass.textChanged(_:)), for: UIControlEvents.editingChanged ) 

usando clase como:

 class MyClass { func textChanged(sender: Any!) { } } 

Swift 4

 func addNotificationObservers() { NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidChangeAction(_:)), name: .UITextFieldTextDidChange, object: nil) } @objc func textFieldDidChangeAction(_ notification: NSNotification) { let textField = notification.object as! UITextField print(textField.text!) } 

Debe usar la notificación para resolver este problema, porque el otro método escuchará el cuadro de entrada y no la entrada real, especialmente cuando usa el método de entrada chino. En viewDidload

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFiledEditChanged:) name:@"UITextFieldTextDidChangeNotification" object:youTarget]; 

entonces

 - (void)textFiledEditChanged:(NSNotification *)obj { UITextField *textField = (UITextField *)obj.object; NSString *toBestring = textField.text; NSArray *currentar = [UITextInputMode activeInputModes]; UITextInputMode *currentMode = [currentar firstObject]; if ([currentMode.primaryLanguage isEqualToString:@"zh-Hans"]) { UITextRange *selectedRange = [textField markedTextRange]; UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0]; if (!position) { if (toBestring.length > kMaxLength) textField.text = toBestring; } 

}

finalmente, corres, lo harás.

Swift 3.1:

Selector: ClassName.MethodName

  cell.lblItem.addTarget(self, action: #selector(NewListScreen.fieldChanged(textfieldChange:)), for: .editingChanged) func fieldChanged(textfieldChange: UITextField){ } 

Con cierre:

  class TextFieldWithClosure: UITextField { var targetAction: (() -> Void)? { didSet { self.addTarget(self, action: #selector(self.targetSelector), for: .editingChanged) } } func targetSelector() { self.targetAction?() } } 

y usando

 textField.targetAction? = { // will fire on text changed } 
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeTextViewText:) name:UITextFieldTextDidChangeNotification object:nil]; - (void) didChangeTextViewText { //do something } 

Versión de Swift 3:

 class SomeClass: UIViewController, UITextFieldDelegate { @IBOutlet weak var aTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() aTextField.delegate = self aTextField.addTarget(self, action: #selector(SignUpVC.textFieldDidChange), for: UIControlEvents.editingChanged) } func textFieldDidChange(_ textField: UITextField) { //TEXT FIELD CHANGED..SECRET STUFF } } 

No te olvides de configurar el delegado.

Versión de Swift 3

 yourTextField.addTarget(self, action: #selector(YourControllerName.textChanges(_:)), for: UIControlEvents.editingChanged) 

Y consigue los cambios aquí

 func textChanges(_ textField: UITextField) { let text = textField.text! // your desired text here // Now do whatever you want. } 

Espero eso ayude.

Es realmente simple con observador y rápido reactivo (RxCocoa & RxSwift).

Simplemente suscríbase a la propiedad de texto de rx, como a continuación:

 myTextField.rx.text.subscribe { text in print("UITextFieldTextChangeEvent Text:\(text)") }.disposed(by: disposeBag) 

Swift 3

 @IBAction func textfildChange(sender: UITextField) { if let number = sender.text { if number.isEmpty { } else { print(number) } } }