要限制一个UITextField的输入字数,很多人首先想到的是通过UITextFieldDelegate下面这个代理方法实现:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;//return NO to not change text
例如要设置字数限制为10:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == self.titleField) {
if (textField.length >= 10) return NO;
}
return YES;
}
此列的缺点:
1、此时要添加到textField的文字并未写入textField,我们判断的是已经输入的文字是否超过10个,如果输入了9个,然而最后一次直接拼音出来好几个字,此时也是可以输入的,所以range和string参数是一定要使用的,range说明文字要插入的文字将要放置的位置,string为将要插入的字符串。
2、联想词的输入不通知此代理函数,所以如果通过联想词输入的话,想输入多少文字都可以
3、输入超过10个字之后退格键不能用
4、当使用拼音输入法时,该委托方法中的最后一个参数string接受的是输入的字母,而不是选择的汉字,造成的结果是,当想输入文字“我在编程”,输入拼音“wozaibiancheng”,每输入一个字母便会进入委托方法,统计的字符长度是字母的长度,实际上汉字还未超过限制长度,但是字母的长度超过了导致无法继续输入。而且,致命的是,这个委托方法并不响应,选中候选汉字的过程即这个委托方法没有响应最后拼音到汉字的过程),这就没有办法重新修正字符长度的统计了。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == self.titleField) {
if (string.length == 0) return YES;
NSMutableString *newtxt = [NSMutableString stringWithString:textField.text];
[newtxt replaceCharactersInRange:range withString:string];
if (newtxt.length > 10) return NO;
}
return YES;
}
此列的缺点:
1、联想词的输入不通知此代理函数,所以如果通过联想词输入的话,想输入多少文字都可以
2、输入超过10个字之后退格键不能用
3、当使用拼音输入法时,该委托方法中的最后一个参数string接受的是输入的字母,而不是选择的汉字,造成的结果是,当想输入文字“我在编程”,输入拼音“wozaibiancheng”,每输入一个字母便会进入委托方法,统计的字符长度是字母的长度,实际上汉字还未超过限制长度,但是字母的长度超过了导致无法继续输入。而且,致命的是,这个委托方法并不响应,选中候选汉字的过程(即这个委托方法没有响应最后拼音到汉字的过程),这就没有办法重新修正字符长度的统计了。
对于联想词的问题,我们还可以通过-(void)textFieldDidEndEditing:(UITextField *)textField;代理方法在结束编辑的时候把文本截断,但是用户体验很差,因为用户会看到输入的文字在输入完成时突然少了几个。此时希望有类似-(void)textFieldDidChange:(UITextField *)textField的代理方法,但可惜没有。不过天无绝人之路,UITextField有UIKIT_EXTERN NSString *const UITextFieldTextDidChangeNotification这个消息通知(切记,监听消息还要记得解除监听),UITextField本身提供了相应的事件监听:
[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
这样就可以更好地限制输入长度:
- (void)textFieldDidChange:(UITextField *)textField
{
if (textField == self.titleField) {
if (textField.text.length > 10) {
textField.text = [textField.text substringToIndex:10];
}
}
}
此列的缺点:
1、对于纯字符的统计没有什么问题,但是,当使用拼音输入法时,该方法中的最后一个参数string接受的是输入的字母,而不是选择的汉字,造成的结果是,当想输入文字“我在编程”,输入拼音“wozaibiancheng”,每输入一个字母便会进入方法,统计的字符长度是字母的长度,实际上汉字还未超过限制长度,但是字母的长度超过了导致无法继续输入。
解决办法如下:
- (void) textFieldDidChange:(UITextField *)textField
{
NSInteger kMaxLength = 8;
NSString *toBeString = textField.text;
NSString *lang = [[UIApplication sharedApplication]textInputMode].primaryLanguage; //ios7之前使用[UITextInputMode currentInputMode].primaryLanguage
if ([lang isEqualToString:@"zh-Hans"]) { //中文输入
UITextRange *selectedRange = [textField markedTextRange];
//获取高亮部分
UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
if (!position) {// 没有高亮选择的字,则对已输入的文字进行字数统计和限制
if (toBeString.length > kMaxLength) {
textField.text = [toBeString substringToIndex:kMaxLength];
}
}
else{//有高亮选择的字符串,则暂不对文字进行统计和限制
}
}else{//中文输入法以外的直接对其统计限制即可,不考虑其他语种情况
if (toBeString.length > kMaxLength) {
textField.text = [toBeString substringToIndex:kMaxLength];
}
}
}