UITextView字数限制坑一天o(╯□╰)o
近期做个小小需求的时候碰到个小问题
起初以为字数限制而已,一丢丢的小功能,用textView:shouldChangeTextInRange:shouldChangeTextInRange:方法在输入前判断是否可变更值即可。
结果慢慢的一个又一个的坑就出现了。
坑一:
iOS9以下,中文输入的情况下,点击联想字输入是不会回调textView:shouldChangeTextInRange:shouldChangeTextInRange:这个方法的。
于是,联想词各种狂点。 一小会输入框满满全是~~~~
好吧。只能在textViewDidChange:方法内判断了。
于是,唰唰唰在textViewDidChange:中加入三行代码。
if(textView.text.length>NM_CARREPORT_TEXTLENGTH_MAX){
textView.text=[textView.text substringToIndex:NM_CARREPORT_TEXTLENGTH_MAX];
}
果断run起来,开始噼里啪啦的狂敲屏幕自测【其实是抽空休息来着】。
“Bon…” crash了!!!
纳尼?! what are you 弄啥嘞?!!!我玩个textView,你要是crash在string相关的也就算了。 你特喵崩在array这种玩意上是闹哪样!!!
惆怅了半天,,好吧,,继续填坑。。。
坑二
crash是在textView截断的时候出现,唔,setMarkedText:selectedRange:是设置文字,然后内部进行富文本的替换。
苦思冥想半天,真真是不得其解,为啥崩了。
直到,突然发现在中文输入下,连续输入声母中间会出现空格, 哇咔咔~~ 悟了 O(∩_∩)O哈哈哈~
赶紧验证一下自己的想法,果然。。。
崩溃的原因在于,假设要设置的上限是100个字符,当输入98个字符以后,连续输入两个声母,此时系统自动在中间添加一个空格,进入到textViewDidChanged:中,textView.text的长度变成101,进入到截断字符串的逻辑中,截掉最后一个字符,那么剩余100个字符的最后一个是系统自动增加的空格。将整个串重新赋给textView.text的时候,系统无法识别空格(特喵的自己生的都不认。日了狗了了~~),于是就华丽丽的崩了。【经检验,若最后两个字符输入的是形如ch酱紫的,不会产生空格的连续字符,就不会有问题】。
不过也对,原本textView:shouldChangeTextInRange:shouldChangeTextInRange:就是用来过滤输入文本的,既然进入到textViewDidChange:中了,自然文本就是需要的,岂能容你随意更改!【so。 机智的苹果偷偷摸摸的在iOS9上更改了联想文字输入的逻辑。也走textView:shouldChangeTextInRange:shouldChangeTextInRange:方法了】
问题找到了,接下来就是填坑了。
机智如我,小小问题岂能难倒,
if(textView.text.length>NM_CARREPORT_TEXTLENGTH_MAX+1){
textView.text=[textView.text substringToIndex:NM_CARREPORT_TEXTLENGTH_MAX+1];
}
哈哈。宝宝是不是好机智,酱紫正常输入就不会进入到该方法了!因为在textView:shouldChangeTextInRange:shouldChangeTextInRange:中已经限制了。 而联想输入,就让你多输入一个字嘛~ 反正一般人看不出来。
坑三
天真的我低估了我厂QA同学的敬业程度,居然生生测出这BUG。 101个字和100个字~~~!!! 我说同学,你要不要这么屌。。。。 一个个去数你也是棒棒哒!!!
既然QA同学提出意见了。作为一名敬业的RD。必须fix掉啊!
然而。。。 天知道怎么搞。。。 机(bai)智(wu)如(liao)我(lai),继续翻API找去。
咦?!markedTextRange 这个是什么鬼?!
/* If text can be selected, it can be marked. Marked text represents provisionally
* inserted text that has yet to be confirmed by the user.It requires unique visual
* treatment in its display.If there is any marked text, the selection, whether a
* caret or an extended range, always resides witihin.
*
* Setting marked text either replaces the existing marked text or, if none is present,
* inserts it from the current selection. */
好吧。直译就是标记文本,代表临时的插入待用户确认的文本,简单来说,这个其实就是中文输入时,高亮的英文部分。。中文输入下并且有高亮的英文部分时,这玩意儿就有值了。
到这里,这坑就填一半了。
if(textView.text.length > NM_CARREPORT_TEXTLENGTH_MAX && textView.markedTextRange == nil){
textView.text=[textView.text substringToIndex:NM_CARREPORT_TEXTLENGTH_MAX];
}
呼,搞定~~