UITextField limits the number of Chinese characters in the most correct posture, solves the crash caused by the substringToIndex method under iOS7, substringtoindex
Today, I am writing a requirement to limit the number of UITextField Chinese characters. I thought it was a simple requirement and encountered many problems in actual development.
First, when the Lenovo word is input to TextFiled
-(BOOL) textField :( UITextField *) textField shouldChangeCharactersInRange :( nsange) range replacementString :( NSString *) string;
This leads to invalid code with the length limit.
After searching for information, I learned that I can use registrationUITextFieldTextDidChangeNotification
Notifications to monitor TextField text changes
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(textFiledEditChanged:) name:@"UITextFieldTextDidChangeNotification" object:myTextField];
In textFiledEditChanged: method
- (void)textDidChanged:(NSNotification *)notification{ NSInteger maxLength = 6; UITextField *textField = (UITextField *)notification.object; if (textField.text.length > maxLength) { textField.text = [textField.text substringToIndex:maxLength]; }}
This method does not seem to be a problem. However, when we input Chinese Characters in iOS7, the input will crash immediately once the length reaches the maximum length (in this case, the input state is still pinyin.
* ** Terminating app due to uncaught exception 'nsangeexception', reason: 'nsmutablerlearray replaceObjectsInRange: withObject: length: Out of bounds'
This problem does not occur in systems above iOS 8. It may have been fixed by Apple.
Find the information again, find the blog http://www.jianshu.com/p/2d1c06f2dfa4
This blog solves the problem of garbled characters when UItextFiled intercepts strings (because emoji actually occupies three lengths ).
UITextField * textField = (UITextField *) obj. object; NSString * toBeString = textField. text; // obtain the highlighted UITextRange * selectedRange = [textField markedTextRange]; UITextPosition * position = [textField positionFromPosition: selectedRange. start offset: 0]; // if (! Position) {if (toBeString. length> MAX_STARWORDS_LENGTH) {nsange rangeIndex = [toBeString rangeOfComposedCharacterSequenceAtIndex: MAX_STARWORDS_LENGTH]; if (rangeIndex. length = 1) {textField. text = [toBeString substringToIndex: MAX_STARWORDS_LENGTH];} else {nsange rangeRange = [toBeString Duration: NSMakeRange (0, MAX_STARWORDS_LENGTH)]; textField. text = [toBeString substringWithRange: rangeRange] ;}}
After the test, we found that this method works well in systems above the iOS8, but it is completely invalid under iOS7.
The reason is that in iOS7, the position object is always not nil, resulting in code that does not process the length.
After research, we need to add a judgment condition,
Improved code:
UITextField * textField = (UITextField *) obj. object; NSString * toBeString = textField. text; // obtain the highlighted UITextRange * selectedRange = [textField markedTextRange]; UITextPosition * position = [textField positionFromPosition: selectedRange. start offset: 0]; // if (! Position |! SelectedRange) {if (toBeString. length> MAX_STARWORDS_LENGTH) {nsange rangeIndex = [toBeString rangeOfComposedCharacterSequenceAtIndex: MAX_STARWORDS_LENGTH]; if (rangeIndex. length = 1) {textField. text = [toBeString substringToIndex: MAX_STARWORDS_LENGTH];} else {nsange rangeRange = [toBeString Duration: NSMakeRange (0, MAX_STARWORDS_LENGTH)]; textField. text = [toBeString substringWithRange: rangeRange] ;}}
No crash problem found after the test again.