限制字数的textview

好久没有写文章了,今天上来写写,发现增多了markDown编辑器。挺不错,后续研究一下,今天暂写文章先。好了,不废话。

如题,相信大家看到这个标题都不想看文章了,这有什么好说的,网上一搜一大把。好吧,自认为是一搜一大把的跳过,有兴趣的就看完。。。。。。

对于限制UITextView输入的字符数。相信大家在网上见得最多的是实现UITextViewDelegate

[objc] view plain copy

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range  

 replacementText:(NSString *)text;//有输入时触但对于中文键盘出示的联想字选择时不会触发  


- (void)textViewDidChange:(UITextView *)textView;//当输入且上面的代码返回YES时触发。或当选择键盘上的联想字时触发。  

第一个用于限制输入,第二个用于动态计算剩余字数。好吧,就来慢慢的给大家分析这两个代理共同协作来限制输入。

从最简单的开始。为了便于讲析,声明

#define MAX_LIMIT_NUMS 100 来限制最大输入只能100个字符

详细的实现代码:

[objc] view plain copy

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range  

 replacementText:(NSString *)text  

{  

NSString *comcatstr = [textView.text stringByReplacingCharactersInRange:range withString:text];  


NSInteger caninputlen = MAX_LIMIT_NUMS - 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 = [text substringWithRange:rg];  


[textView setText:[textView.text stringByReplacingCharactersInRange:range withString:s]];  

        }  

return NO;  

    }  


}  


- (void)textViewDidChange:(UITextView *)textView  

{  

NSString  *nsTextContent = textView.text;  

NSInteger existTextNum = nsTextContent.length;  


if (existTextNum > MAX_LIMIT_NUMS)  

    {  

//截取到最大位置的字符  

NSString *s = [nsTextContent substringToIndex:MAX_LIMIT_NUMS];  


[textView setText:s];  

    }  


//不让显示负数  

self.lbNums.text = [NSString stringWithFormat:@"%ld/%d",MAX(0,MAX_LIMIT_NUMS - existTextNum),MAX_LIMIT_NUMS];  

}  

最终运行效果:

图片这么大?^_^。大家看到这是不是就表示OK了呢。就提交代码了呢?

好,下面就对上面的简单代进行逐一BUG找出且进行修复。

1.遗留BUG(只考虑了英文键盘下处理)

  上述代码在英文键盘下基本上是可以正常,但如果是在中文(生在天朝啊必须得懂中文)或9宫格键盘下会有什么问是呢。下图是我截图,当输入到只剩下一个字时,这时输入拼音时,问题出现了,发现拼音输不完。另一个问题是当离字数上限差距很大时,输入拼音会发现字数也跟着计算了。本来还没有输入的,此时开始计算了,有瘕次。

如图,在最后一个,本想输入一个拼音h开头的且还没有出现在推荐字的。哪再输入第二位拼音时发现不能输了,且字数被计算了。

对上述可能有朋友说,这算什么BUG。基本上没怎么碰到这情况。嗯确实,但如果是在一段字中间插入的时候呢。这个是有可能出现的。

哪么怎么样处理这样的产生的BUG呢。从分析来看事实上输入拼音还处于高亮状态,哪么有没有什么办法来获取呢。于是呼搜寻中。。。。。。

Ok,确实有这样的好。加上后代码如下:

[objc] view plain copy

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range  

 replacementText:(NSString *)text  

{  

UITextRange *selectedRange = [textView markedTextRange];  

//获取高亮部分  

UITextPosition *pos = [textView positionFromPosition:selectedRange.start offset:0];  

//获取高亮部分内容  

//NSString * selectedtext = [textView textInRange:selectedRange];  


//如果有高亮且当前字数开始位置小于最大限制时允许输入  

if (selectedRange && pos) {  

NSInteger startOffset = [textView offsetFromPosition:textView.beginningOfDocument toPosition:selectedRange.start];  

NSInteger endOffset = [textView offsetFromPosition:textView.beginningOfDocument toPosition:selectedRange.end];  

        NSRange offsetRange = NSMakeRange(startOffset, endOffset - startOffset);  


if (offsetRange.location < MAX_LIMIT_NUMS) {  

return YES;  

        }  

else  

        {  

return NO;  

        }  

    }  



NSString *comcatstr = [textView.text stringByReplacingCharactersInRange:range withString:text];  


NSInteger caninputlen = MAX_LIMIT_NUMS - 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 = [text substringWithRange:rg];  


[textView setText:[textView.text stringByReplacingCharactersInRange:range withString:s]];  

//既然是超出部分截取了,哪一定是最大限制了。  

self.lbNums.text = [NSString stringWithFormat:@"%d/%ld",0,(long)MAX_LIMIT_NUMS];  

        }  

return NO;  

    }  


}  


- (void)textViewDidChange:(UITextView *)textView  

{  

UITextRange *selectedRange = [textView markedTextRange];  

//获取高亮部分  

UITextPosition *pos = [textView positionFromPosition:selectedRange.start offset:0];  


//如果在变化中是高亮部分在变,就不要计算字符了  

if (selectedRange && pos) {  

return;  

    }  


NSString  *nsTextContent = textView.text;  

NSInteger existTextNum = nsTextContent.length;  


if (existTextNum > MAX_LIMIT_NUMS)  

    {  

//截取到最大位置的字符  

NSString *s = [nsTextContent substringToIndex:MAX_LIMIT_NUMS];  


[textView setText:s];  

    }  


//不让显示负数 口口日  

self.lbNums.text = [NSString stringWithFormat:@"%ld/%d",MAX(0,MAX_LIMIT_NUMS - existTextNum),MAX_LIMIT_NUMS];  

}  

推荐阅读更多精彩内容