Using the notification center, as described in How can I get a textDidChange (like for a UISearchBar) method for a UITextField?, allows you to get a notification when text in an iOS UITextField changes. I didn't see a similar notification for selection changes. What's the best way to detect and respond to changes in the selection for a UITextField?
4 Answers
This link has one solution without messing with private apis:
In short: Subclass UITextField, implement
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
and check if the selection range has changed. But this does not notify about taps.
So what I did is after subclassing, observe the selectedTextRange
property:
-(void)awakeFromNib {
[self addObserver:self forKeyPath:@"selectedTextRange" options:0 context:nil];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
[self notifyDelegateIfNecessary];
}
Works very well in iOS8.

- 630
- 1
- 8
- 16
-
1why you don't override [UITextField setSelectedTextRange:(UITextRange *)selectedTextRange] if you anyway did subclass UITextField? Then all changes come along in this place. – Leo Jun 13 '16 at 14:33
-
@Leo 1. I do not want to change the behavior, only get notifications 2. I just checked in PlayGround and I think you cannot override that function. – Krisdigital Jun 14 '16 at 11:51
-
It works for me (IOS 8+9). This way I surround the needs to remove the observer at the suitable place. – Leo Jun 14 '16 at 12:12
-
Your choice, I would not override a private method, but probably a thing of taste. – Krisdigital Jun 14 '16 at 13:24
-
1@Krisdigital if you override *setSelectedTextRange* and in its implementation call *[super setSelectedTextRange:text]*, you'll maintain the original behavior of the superclass but also get a notification point – nalexn Nov 24 '16 at 16:34
-
@NAlexN I know, feel free to override to your liking ;) – Krisdigital Nov 27 '16 at 16:13
There is simple way to detect selection in textField
add object property observer in viewDidAppear
[self.keyboardInputFieldPassword addObserver:self forKeyPath:@"selectedTextRange" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
Then Add observe function for property
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if([keyPath isEqualToString:@"selectedTextRange"] && self.keyboardInputFieldPassword == object)
[self textFieldDidChangeSelection:self.keyboardInputFieldPassword];
}
This will capture the selection range in UITextField
For following the convention, you should removeObserver in viewDidDisappear
[self.keyboardInputFieldPassword removeObserver:self forKeyPath:@"selectedTextRange" context:nil];

- 173
- 1
- 9
Swift 4
private func listenForSelection(in textField:UITextField) {
textField.addObserver(self, forKeyPath: "selectedTextRange", options: [.new,.old], context: nil)
}
private func unlistenForSelection(in textField:UITextField) {
textField.removeObserver(self, forKeyPath: "selectedTextRange")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
let textField = object as? UITextField
assert(keyPath == "selectedTextRange")
assert(textField != nil)
// select everything but the first and last characters - just and example of the UITextInput API if you want to modify the selection
if let startPosition = textField.position(from: textField.beginningOfDocument, offset: 1),
let endPosition = textField.position(from: textField.endOfDocument, offset: -1) {
let selectionRange = textField.textRange(from: startPosition, to: endPosition)
textField.selectedTextRange = selectionRange
}
}

- 8,217
- 1
- 37
- 43
Wire up a method using target/action to the UIControlEventEditingChanged
control event on your instance of UITextField
. This can be done in the interface builder or in code by adding a target/action pair to the text field and then implementing the specified method.
[self.textField addTarget:self action:@selector(textFieldTextChanged:) forControlEvents:UIControlEventEditingChanged];
UITextField
also declares a UITextFieldDelegate
protocol with methods that you can implement in your class to be notified of changes to an instance of UITextField
. I recommend that you become comfortable with delegation as it is a common pattern in the Cocoa framework.

- 30,776
- 11
- 77
- 77
-
4[`UIControlEventEditingChanged`](http://developer.apple.com/library/ios/documentation/uikit/reference/UIControl_Class/Reference/Reference.html#//apple_ref/doc/c_ref/UIControlEventEditingChanged) only refers to text edits. I.e., the action only fires when the text changes while the text field `isEditing`. This doesn't include selection changes. – ma11hew28 Jul 06 '12 at 02:38