How can I detect any text changes in a textField? The delegate method shouldChangeCharactersInRange
works for something, but it did not fulfill my need exactly. Since until it returns YES, the textField texts are not available to other observer methods.
e.g. in my code calculateAndUpdateTextFields
did not get the updated text, the user has typed.
Is their any way to get something like textChanged
Java event handler.
- (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;
}
As stated here: UITextField text change event, it seems that as of iOS 6 (iOS 6.0 and 6.1 checked) it is not possible to fully detect changes in
UITextField
objects just by observing theUITextFieldTextDidChangeNotification
.It seems that only those changes made directly by the built-in iOS keyboard are tracked now. This means that if you change your
UITextField
object just by invoking something like this:myUITextField.text = @"any_text"
, you won't be notified about any changes at all.I don't know if this is a bug or it is intended. Seems like a bug since I haven't found any reasonable explanation in documentation. This is also stated here: UITextField text change event.
My "solution" to this is to actually post a notification by myself for every change I make to my
UITextField
(if that change is done without using the built-in iOS keyboard). Something like this:This way you are 100% confident that you'll receive the same notification when you change the
.text
property of yourUITextField
object, either when you update it "manually" in your code or through the built-in iOS keyboard.It is important to consider that, since this is not a documented behavior, this approach may lead to 2 notifications received for the same change in your
UITextField
object. Depending on your needs (what you actually do when yourUITextField.text
changes) this could be an inconvenience for you.A slightly different approach would be to post a custom notification (this is, with a custom name other than
UITextFieldTextDidChangeNotification
) if you actually need to know whether the notification was yours or "iOS-made".EDIT:
I've just found a different approach which I think could be better:
This involves the Key-Value Observing (KVO) feature of Objective-C (http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177-BCICJDHA).
Basically, you register yourself as an observer of a property and if this property changes you get notified about it. The "principle" is quite similar to how
NSNotificationCenter
works, being the main advantage that this approach works automatically also as of iOS 6 (without any special tweak like having to manually post notifications).For our
UITextField
-scenario this works just fine if you add this code to, for example, yourUIViewController
that contains the text field:Credit to this answer regarding "context" management: https://stackoverflow.com/a/12097161/2078512
Note: Seems like while you are in the process of editing a
UITextField
with the built-in iOS keyboard, the "text" property of the text field is not updated with every new letter typed/removed. Instead, the text field object gets updated "as a whole" after you resign the first responder status of the text field.Swift Version tested:
Parameters explained:
Then add the method you created above in your
UIViewController
:For Swift 3.0:
using class like:
It's really simple with observer and reactive swift (RxCocoa & RxSwift).
Just subscribe to text property of rx, Like below:
to set the event listener:
to actually listen:
I resolved the issue changing the behavior of shouldChangeChractersInRange. If you return NO the changes won't be applied by iOS internally, instead you have the opportunity to change it manually and perform any actions after the changes.