How can I get a textDidChange method for a UITextField? I need to call a method every time a change is made to a text field. Is this possible? Thanks!
8 Answers
You can use the UITextFieldTextDidChangeNotification
to call a method whenever the text field changes. Add this to your init
:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:UITextFieldTextDidChangeNotification object:nil];

- 3,007
- 4
- 30
- 37
-
4The advantage to this method over Ben's answer is that you can be notified *after* the text changes. If you use `shouldChangeCharactersInRange` you have to try to calculate how the string will look once the edit has been allowed. – Andrew Feb 22 '12 at 08:00
-
@Andrew - You say that as if it's hard. Just use `[[textField.text mutableCopy] replaceCharactersInRange:range withString:string]` to get the post-change string. – ArtOfWarfare Nov 11 '12 at 00:38
-
Actually, it's not quite that easy. You need to add a local variable to hold the NSMutableString returned by `[[textField.text] mutableCopy]`, then use the replace method on that local variable, then do whatever you want with the local variable, just because it returns void rather than the changed string. – ArtOfWarfare Nov 11 '12 at 00:45
-
This works like a champ! I'm using it to parse a full name field into first and last names in real time and it's *perfect*! – mpemburn Feb 07 '13 at 19:34
-
This is not working for me in ios 7. I tried this and added a function textDidChange but the function is never called. – Mike S Jan 03 '14 at 01:09
-
Make sure that wherever you put the addObserver line is being called. For example, init is not called if your view is loaded from an interface builder file. – shim May 10 '14 at 19:32
You can setup a delegate and use
- (BOOL) textField: (UITextField *) textField shouldChangeCharactersInRange: (NSRange) range replacementString: (NSString *) string;

- 85,404
- 22
- 176
- 172
-
3Thanks! That worked beautifully. I had to do the following to get the full string: NSMutableString *textFieldString = [NSMutableString stringWithString:textField.text]; [textFieldString appendString:string]; – Jonah Dec 17 '09 at 04:41
-
For all you noobs like myself out there. This is a delegate method that you drop in as is. It will give you the complete text entered plus the last character typed. Excellent! – Eric Brotto Dec 12 '11 at 18:14
-
9This is not a good approach. This method fires before the text changes, so the text you are looking at is not what the user just typed, and appending the replacementString to the existing text is not right either because the user might be inserting the text in the middle of the previous string, or replacing it altogether (that's why there's a range parameter). Save yourself a headache and use Chris's solution below instead. – Nick Lockwood Aug 28 '12 at 15:14
-
this solution also breaks for backspaces or deleting characters unless you manually call the ```replaceCharactersInRange``` method... – Andrew Aug 17 '15 at 21:20
You can also a target & selector for the UIControlEventEditingChanged
event. For example:
[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]
Note that this will only be called for user initiated changes to the text field and will not be called automatically when programmatically setting text.

- 15,200
- 21
- 100
- 172
Elaborating further on Ben Gottlieb's answer above, using textField shouldChangeCharactersInRange is great but has the disadvantage that some things can happen with a one character delay.
Eg calling the below to alert you when there is no text actually is called the character after, once you have enter a character and it is no longer empty.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (!textField.text.length) {
// Do something with empty textfield
}
return YES;
}
The below method allows you to get a rudimentary change happening in your textField. Although not quite as direct as an NSNotification it still allows you to use similar methods with different textFields and so is a pretty useful thing to use when trying to get specific character changes in your textfield.
The below code fixes the character delay
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// This means it updates the name immediately
NSString * newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
textField.placeholder = newString.length ? @"" : @"Name";
return YES;
}
For this code is used to add a placeholder to a UITextField when there is no text in the textField

- 6,023
- 3
- 43
- 60
I found some problem when you use replaceCharactersInRange
in delegate shouldChangeCharactersInRange.
Ex: In Vietnamese keyboard string aa
-> â
, So if you use method replaceCharactersInRange
then Incorrect results.
You can try in this case by event UIControlEventEditingChanged
:
[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]

- 2,152
- 1
- 23
- 26

- 306
- 4
- 8
-
I had exactly the same problem. For example: If the textfield's text is "Ha" and replacementString is "f" and if I use function `- (BOOL) textField: (UITextField *) textField shouldChangeCharactersInRange: (NSRange) range replacementString: (NSString *) string`, the actual result will be "Haf" but the expect result should be "Hà" in Vietnamese. – Duan Nguyen Nov 14 '17 at 02:53
Swift Solution
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let newString = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
return true
}

- 3,733
- 1
- 35
- 36
Below is what I used Swift 4
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let fieldText = textField.text else {
return false
}
// Append the existing textfield text with the new character
var text = fieldText + string
// If it is the very first character, textfield text will be empty so take the 'string' and on delete also textfield text get deleted with a delay
if range.location == 0{
text = string
}
return true
}

- 7,598
- 4
- 53
- 56
Simply:
class MTextField: NSTextField {
override func textDidChange(_ notification: Notification) {
//...
}
}
In Obj-C (not check):
@interface MTextField: NSTextField
@end
@implementation MTextField
- (void) textDidChange:(NSNotification*) notification {
//...
}
@end

- 320
- 2
- 6