好久沒(méi)有寫文章了,今天上來(lái)寫寫信殊,發(fā)現(xiàn)增多了markDown編輯器秧廉。挺不錯(cuò)伞广,后續(xù)研究一下,今天暫寫文章先疼电。好了嚼锄,不廢話。
如題蔽豺,相信大家看到這個(gè)標(biāo)題都不想看文章了区丑,這有什么好說(shuō)的,網(wǎng)上一搜一大把修陡。好吧沧侥,自認(rèn)為是一搜一大把的跳過(guò),有興趣的就看完魄鸦。宴杀。。拾因。旺罢。。
對(duì)于限制UITextView輸入的字符數(shù)绢记。相信大家在網(wǎng)上見(jiàn)得最多的是實(shí)現(xiàn)UITextViewDelegate
[objc]?view plain?copy
-?(BOOL)textView:(UITextView?*)textView?shouldChangeTextInRange:(NSRange)range??
?replacementText:(NSString?*)text;//有輸入時(shí)觸但對(duì)于中文鍵盤出示的聯(lián)想字選擇時(shí)不會(huì)觸發(fā)??
-?(void)textViewDidChange:(UITextView?*)textView;//當(dāng)輸入且上面的代碼返回YES時(shí)觸發(fā)扁达。或當(dāng)選擇鍵盤上的聯(lián)想字時(shí)觸發(fā)蠢熄。??
第一個(gè)用于限制輸入跪解,第二個(gè)用于動(dòng)態(tài)計(jì)算剩余字?jǐn)?shù)。好吧签孔,就來(lái)慢慢的給大家分析這兩個(gè)代理共同協(xié)作來(lái)限制輸入惠遏。
從最簡(jiǎn)單的開(kāi)始砾跃。為了便于講析,聲明
#define MAX_LIMIT_NUMS?100 來(lái)限制最大輸入只能100個(gè)字符
詳細(xì)的實(shí)現(xiàn)代碼:
[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;??
//防止當(dāng)text.length?+?caninputlen?<?0時(shí)节吮,使得rg.length為一個(gè)非法最大正數(shù)出錯(cuò)??
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];??
????}??
//不讓顯示負(fù)數(shù)??
self.lbNums.text?=?[NSString?stringWithFormat:@"%ld/%d",MAX(0,MAX_LIMIT_NUMS?-?existTextNum),MAX_LIMIT_NUMS];??
}??
最終運(yùn)行效果:
圖片這么大?^_^判耕。大家看到這是不是就表示OK了呢透绩。就提交代碼了呢?
好壁熄,下面就對(duì)上面的簡(jiǎn)單代進(jìn)行逐一BUG找出且進(jìn)行修復(fù)帚豪。
1.遺留BUG(只考慮了英文鍵盤下處理)
? 上述代碼在英文鍵盤下基本上是可以正常,但如果是在中文(生在天朝啊必須得懂中文)或9宮格鍵盤下會(huì)有什么問(wèn)是呢草丧。下圖是我截圖狸臣,當(dāng)輸入到只剩下一個(gè)字時(shí),這時(shí)輸入拼音時(shí)昌执,問(wèn)題出現(xiàn)了烛亦,發(fā)現(xiàn)拼音輸不完。另一個(gè)問(wèn)題是當(dāng)離字?jǐn)?shù)上限差距很大時(shí)懂拾,輸入拼音會(huì)發(fā)現(xiàn)字?jǐn)?shù)也跟著計(jì)算了煤禽。本來(lái)還沒(méi)有輸入的,此時(shí)開(kāi)始計(jì)算了岖赋,有瘕次檬果。
如圖,在最后一個(gè)唐断,本想輸入一個(gè)拼音h開(kāi)頭的且還沒(méi)有出現(xiàn)在推薦字的选脊。哪再輸入第二位拼音時(shí)發(fā)現(xiàn)不能輸了,且字?jǐn)?shù)被計(jì)算了脸甘。
對(duì)上述可能有朋友說(shuō)恳啥,這算什么BUG〗锍蹋基本上沒(méi)怎么碰到這情況角寸。嗯確實(shí),但如果是在一段字中間插入的時(shí)候呢忿墅。這個(gè)是有可能出現(xiàn)的扁藕。
哪么怎么樣處理這樣的產(chǎn)生的BUG呢。從分析來(lái)看事實(shí)上輸入拼音還處于高亮狀態(tài)疚脐,哪么有沒(méi)有什么辦法來(lái)獲取呢亿柑。于是呼搜尋中。棍弄。望薄。疟游。。痕支。
Ok,確實(shí)有這樣的好颁虐。加上后代碼如下:
[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];??
//獲取高亮部分內(nèi)容??
//NSString?*?selectedtext?=?[textView?textInRange:selectedRange];??
//如果有高亮且當(dāng)前字?jǐn)?shù)開(kāi)始位置小于最大限制時(shí)允許輸入??
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;??
//防止當(dāng)text.length?+?caninputlen?<?0時(shí),使得rg.length為一個(gè)非法最大正數(shù)出錯(cuò)??
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];??
//如果在變化中是高亮部分在變,就不要計(jì)算字符了??
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];??
????}??
//不讓顯示負(fù)數(shù)?口口日??
self.lbNums.text?=?[NSString?stringWithFormat:@"%ld/%d",MAX(0,MAX_LIMIT_NUMS?-?existTextNum),MAX_LIMIT_NUMS];??
}??