本文介绍了UITextView对中英文还有iOS自带表情输入的字数限制,由于中文输入会有联想导致字数限制不准确所以苦恼好久,所以参考一些大神的博客终于搞定,欢迎大家参考和指正。
对于限制UITextView输入的字符数。相信大家在网上见得最多的是实现UITextViewDelegate
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; - (void)textViewDidChange:(UITextView *)textView;
第一个限制输入,有输入时会调用,但是中文下会有问题:中文联想选字时不会调用;
第二个用于动态计算剩余字数,当输入且第一个方法返回YES时触发。或当选择键盘上的联想字时触发。
不多说,直接上代码:
1 #define MAX_LIMIT_NUMS 100 //最大限制字数
1 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{ 2 UITextRange *selectedRange = [textView markedTextRange]; 3 //获取高亮部分 4 UITextPosition *pos = [textView positionFromPosition:selectedRange.start offset:0]; 5 //获取高亮部分内容 6 //NSString * selectedtext = [textView textInRange:selectedRange]; 7 8 //如果有高亮且当前字数开始位置小于最大限制时允许输入 9 if (selectedRange && pos) { 10 NSInteger startOffset = [textView offsetFromPosition:textView.beginningOfDocument toPosition:selectedRange.start]; 11 NSInteger endOffset = [textView offsetFromPosition:textView.beginningOfDocument toPosition:selectedRange.end]; 12 NSRange offsetRange = NSMakeRange(startOffset, endOffset - startOffset); 13 14 if (offsetRange.location < MAX_LIMIT_NUMS) { 15 return YES; 16 } 17 else 18 { 19 return NO; 20 } 21 } 22 23 NSString *comcatstr = [textView.text stringByReplacingCharactersInRange:range withString:text]; 24 25 NSInteger caninputlen = MAX_LIMIT_NUMS - comcatstr.length; 26 27 if (caninputlen >= 0) 28 { 29 return YES; 30 } 31 else 32 { 33 NSInteger len = text.length + caninputlen; 34 //防止当text.length + caninputlen < 0时,使得rg.length为一个非法最大正数出错 35 NSRange rg = {0,MAX(len,0)}; 36 37 if (rg.length > 0) 38 { 39 NSString *s = @""; 40 //判断是否只普通的字符或asc码(对于中文和表情返回NO) 41 BOOL asc = [text canBeConvertedToEncoding:NSASCIIStringEncoding]; 42 if (asc) { 43 s = [text substringWithRange:rg];//因为是ascii码直接取就可以了不会错 44 } 45 else 46 { 47 __block NSInteger idx = 0; 48 __block NSString *trimString = @"";//截取出的字串 49 //使用字符串遍历,这个方法能准确知道每个emoji是占一个unicode还是两个 50 [text enumerateSubstringsInRange:NSMakeRange(0, [text length]) 51 options:NSStringEnumerationByComposedCharacterSequences 52 usingBlock: ^(NSString* substring, NSRange substringRange, NSRange enclosingRange, BOOL* stop) { 53 54 if (idx >= rg.length) { 55 *stop = YES; //取出所需要就break,提高效率 56 return ; 57 } 58 59 trimString = [trimString stringByAppendingString:substring]; 60 61 idx++; 62 }]; 63 64 s = trimString; 65 } 66 //rang是指从当前光标处进行替换处理(注意如果执行此句后面返回的是YES会触发didchange事件) 67 [textView setText:[textView.text stringByReplacingCharactersInRange:range withString:s]]; 69 } 70 return NO; 71 } 72 }
1 -(void)textViewDidChange:(UITextView *)textView 2 { 3 UITextRange *selectedRange = [textView markedTextRange]; 4 //获取高亮部分 5 UITextPosition *pos = [textView positionFromPosition:selectedRange.start offset:0]; 6 //如果在变化中是高亮部分在变,就不要计算字符了 7 if (selectedRange && pos) { 8 return; 9 } 10 NSString *nsTextContent = textView.text; 11 NSInteger existTextNum = nsTextContent.length; 12 13 if (existTextNum > MAX_LIMIT_NUMS) 14 { 15 //截取到最大位置的字符(由于超出截部分在should时被处理了所在这里这了提高效率不再判断) 16 NSString *s = [nsTextContent substringToIndex:MAX_LIMIT_NUMS]; 17 18 [textView setText:s]; 19 }22 }
上述的代码,在输入中,英文,emoji表情符都能正常限制和处理,写到这里基本上能解决输入字符的限制。希望对大家有所帮助,谢谢。过程中还有想不到的或未预见的也希望大家留言给我。我好研究再进行补充。欢迎回馈!