最近项目开发中用到了多行文本框限制文字输入个数限制,之前的话在textViewDidChange方法中截取超出字数就可以。测试人员发现在拼音转汉字的过程中,YYTextView不会二次确认textViewDidChange方法,输入字数只能最后确认结束弹框的时候计算,影响体验效果,后转用自己封装的继承UITextView替换。另外拼音转汉字的情况下,在输入文本中间一直输入,依然会出现输入字数计算不准确的问题。下面列出解决问题实现的代码。
image
pragma mark- UITextViewDelegate
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.activityTextView resignFirstResponder];
}
-(void)updateSpeechButtonStatus{
if (self.activityTextView.text.length >= MAX_NUM) {
self.btnSpeech.enabled = NO;
}else{
self.btnSpeech.enabled = YES;
}
}
//动态显示可输入文本字数
-(void)changeTextNumber:(UITextView *)textView{
if (textView.text.length <= MAX_NUM) {
self.numLabel.text = [NSString stringWithFormat:@"%lu/%lu",(unsigned long)textView.text.length,(MAX_NUM - textView.text.length)];
}else{
self.numLabel.text = [NSString stringWithFormat:@"%@/%@",[NSString stringWithFormat:@"%d",MAX_NUM],@"0"];
}
}
-(void)textViewDidChange:(UITextView *)textView{
UITextRange *selectedRange = [textView markedTextRange];
//获取高亮部分
UITextPosition *pos = [textView positionFromPosition:selectedRange.start offset:0];
//如果是拼音转汉语状态不统计字数,确认输入后统计
if (selectedRange && pos) {
return;
}
[self changeTextNumber:textView];
[self updateSpeechButtonStatus];
}
-(void)textViewDidEndEditing:(UITextView *)textView{
textView.text = [EaseEmoji stringReplaceEmoji:textView.text];
[self changeTextNumber:textView];
[self updateSpeechButtonStatus];
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
BOOL isLimit = [CCCommonAPI textViewTextCountLimit:textView range:range text:text maxCount:[NSString stringWithFormat:@"%d",MAX_NUM] isAllowEmoji:YES completeBlock:^{
//执行这里block的时候不执行textViewDidChange,block里面的内容就是textViewDidChange里面的操作
[self changeTextNumber:textView];
[self updateSpeechButtonStatus];
}];
return isLimit;
}
//textview字数限制处理
-
(BOOL)textViewTextCountLimit:(UITextView *)textView range:(NSRange)range text:(NSString *)text maxCount:(NSString *)maxCountStr isAllowEmoji:(BOOL)isAllowEmoji completeBlock:(nonnull CommonTextLimitCompletion)completeBlock{
if (!isAllowEmoji) {
//不允许输入表情的时候返回NO if ([[[UITextInputMode currentInputMode] primaryLanguage] isEqualToString:@"emoji"]) { return NO; }}
//对于退格删除键开放限制
if (text.length == 0) {return YES;}
NSString *comcatstr = [textView.text stringByReplacingCharactersInRange:range withString:text];
NSInteger caninputlen = [maxCountStr intValue] - comcatstr.length;
if (caninputlen >= 0){
return YES;}else{
NSInteger len = text.length + caninputlen; //防止当text.length + caninputlen < 0时,使得rg.length为一个非法最大正数出错 NSRange rg = {0,MAX(len,0)}; if (rg.length > 0){ NSString *s = @""; //判断是否只普通的字符或asc码(对于中文和表情返回NO) BOOL asc = [text canBeConvertedToEncoding:NSASCIIStringEncoding]; if (asc) { s = [text substringWithRange:rg];//因为是ascii码直接取就可以了不会错 }else{ __block NSInteger idx = 0; __block NSString *trimString = @"";//截取出的字串 //使用字符串遍历,这个方法能准确知道每个emoji是占一个unicode还是两个 [text enumerateSubstringsInRange:NSMakeRange(0, [text length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock: ^(NSString* substring, NSRange substringRange, NSRange enclosingRange, BOOL* stop) { if (idx >= rg.length) { *stop = YES; //取出所需要就break,提高效率 return ; } trimString = [trimString stringByAppendingString:substring]; idx++; }]; s = trimString; } //rang是指从当前光标处进行替换处理(注意如果执行此句后面返回的是YES会触发didchange事件) [textView setText:[textView.text stringByReplacingCharactersInRange:range withString:s]]; completeBlock(); //手动截取更改,不再调用didchange return NO; }else{ UITextRange *selectedRange = [textView markedTextRange]; //获取高亮部分 UITextPosition *pos = [textView positionFromPosition:selectedRange.start offset:0]; if (selectedRange && pos) { //如果拼音转汉语状态继续输入 return YES; }else{ return NO; } }}
}










网友评论