UITextField Monitoring selectedRange

Guides | Tutorial By 4 years ago

In the rare case that you need to monitor UITextField selection changes, there are very few ways to do this. The first is with method swizzling, however this involves messing with private APIs, which can be dangerous. The second is in a place you wouldn’t expect to find it, which is what I’m going to cover.

This example will use my UITextField Selection category from last week, so check that out if you haven’t already.

First of all you’ll need to subclass UITextField. Add a delegate property, I will call mine “selectionDelegate” so it doesn’t interfere with UITextField‘s own delegate property.

@protocol SelectionTextFieldDelegate 
- (void) selectionTextField:(SelectionTextField*) sender changedSelectedRange:(NSRange) selectedRange;

@property (nonatomic, assign) IBOutlet id selectionDelegate;

@synthesize selectionDelegate;

Next I will make a NSRange property for holding our previous selection range. The method we will override will get called multiple times, so this will prevent unnecessarily getting called when we don’t want to know about it.

@interface SelectionTextField ()
	NSRange oldSelectedRange;



// In an init method somewhere...
oldSelectedRange = NSMakeRange(NSNotFound, NSNotFound);

Now time for the magic. Override this method and implement the following:

- (BOOL) canPerformAction:(SEL)action withSender:(id)sender
	const BOOL result = [super canPerformAction:action withSender:sender];

	const NSRange selectedRange = self.selectedRange;

	if(!NSEqualRanges(selectedRange, oldSelectedRange))
		oldSelectedRange = selectedRange;
		[selectionDelegate selectionTextField:self changedSelectedRange:selectedRange];

	return result;

And if you’re super lazy, just download the source here.