I have created a custom UITextField that compares user input against database records. Everything works great until the user puts a space in the text field after I have already suggested something. It crashes the app with the following message:
Terminating app due to uncaught exception ‘NSRangeException’, reason: ‘* -[__NSCFConstantString substringToIndex:]: Range or index out of bounds’
Here is the code:
NSRange cursorRange = [[self valueForKey:@"selectionRange"] rangeValue];
NSString *entered = [self.text substringToIndex:cursorRange.location];
if (![self.text isEqualToString:entered]) {
self.text = entered;
return;
}
NSString *suggestedSuffix;
for (NSString *name in filterData) {
if (name.length > cursorRange.location && [[name lowercaseString] hasPrefix:entered]) {
suggestedSuffix = [name substringFromIndex:cursorRange.location];
NSMutableString *suggestedString = [[NSMutableString alloc] initWithString:entered];
[suggestedString appendString:suggestedSuffix];
self.text = suggestedString;
[self setValue:[NSValue valueWithRange:cursorRange] forKey:@"selectionRange"];
return;
}
}
}
I’m wondering whether you have your key correct?
UITextFielddoes not have aselectionRangeproperty publicly defined AFAICT. However,<UITextInput>– to whichUITextFieldconforms – has aselectedTextRangeproperty. Is this perhaps what you intended? (It’s possible there’s an undocumented private property actually calledselectionRangethat you’ve accidentally encountered, and which doesn’t behave as expected in cases such as you encountered.)Alternatively, did you really mean
UITextView– which has aselectedRange– but still noselectionRange?On a separate note, I don’t think subclassing
UITextFieldis the right approach here. Autocompletion can be completely (no pun intended) implemented using the<UITextFieldDelegate>methods and it is a maxim of Cocoa programming that when you can accomplish a goal through class composition rather than subclassing, you should opt for composition every time.