在第三方鍵盤加入之后,對于字數(shù)限制的處理不再像之前那么簡單了
純數(shù)字、字符輸入(不包括粘貼)這樣的字數(shù)限制還是相對比較簡單的,你可以用兩種方法進行處理
第一種是textfield的delegate實現(xiàn):
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (range.length + range.location > textField.text.length) {
return NO;
}
NSUInteger newLength = textField.text.length + string.length - range.length;
return newLength<=kMaxCharacterCount;
}
第二種是注冊一個通知,在textfield編輯時做處理:
首先你在viewDidLoad中注冊通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFiledEditChanged:) name:UITextFieldTextDidChangeNotification object:self.shopName];
再實現(xiàn)通知里面的方法,在超過最大值時,取最大的字數(shù)
if (self.shopName.text.length > kMaxCharacterCount) {
self.shopName.text = [self.shopName.text substringToIndex:kMaxCharacterCount];
}
但是,在中文的限制上面情況就復(fù)雜了,當(dāng)時在調(diào)試的時候,因為使用的是第三方鍵盤,所以當(dāng)時沒有發(fā)現(xiàn)問題,但是在使用系統(tǒng)鍵盤的時候,一下子就蛋疼了….
下面我開始分析一下,兩者的區(qū)別:1、第三方鍵盤在輸入字符時,一般是不會將字符直接輸入到textfield中,而是將字符顯示在它自己的view上方,但是系統(tǒng)鍵盤會直接輸入到textfield中,而且它會占2個字符長度,比如你輸入”abcd”,在textfield中顯示的是”a b c d”,并且”a b c d”是處在高亮中的,并不算是真正輸入到textfield中,所以我們不應(yīng)把高亮的字符計算在內(nèi),我們應(yīng)該計算真正輸入的字符
2、如果我們使用的是delegate做處理的時候,系統(tǒng)中文輸入的時候會有聯(lián)想,但是聯(lián)想的那個字并不會調(diào)用delegate,比如你輸入一個”你”,在系統(tǒng)的聯(lián)想里面可能會出現(xiàn)”的”,”們”這樣的聯(lián)想,但是你選擇”的”的時候,delegate并不會調(diào)用,(尼瑪….),我猜想聯(lián)想輸入應(yīng)該不算做keyboard所觸發(fā)的事件,所以他并不會觸發(fā)delegate,但是如果你注冊的是通知,他倒是會調(diào)用,(還好有救)
另外提醒一下,有時候在自測輸入的時候,要考慮全面,比如粘貼這也是一種輸入,當(dāng)時沒考慮,我也是跪了
好了,分析了主要的區(qū)別下面我們就來看看具體怎么實現(xiàn)吧~
在實現(xiàn)注冊通知方法里面:
#pragma mark - UITextViewDelegate
- (void)textViewDidChange:(UITextView *)textView {
if (textView.text.length == 0) {
self.recommendTips.hidden = NO;
}else{
self.recommendTips.hidden = YES;
}
NSString *toBeString = textView.text;
NSString *lang = self.textInputMode.primaryLanguage; // 鍵盤輸入模式
if ([lang isEqualToString:@"zh-Hans"]) { // 簡體中文輸入,包括簡體拼音,健體五筆,簡體手寫
UITextRange *selectedRange = [textView markedTextRange];
//獲取高亮部分
UITextPosition *position = [textView positionFromPosition:selectedRange.start offset:0];
// 沒有高亮選擇的字,則對已輸入的文字進行字數(shù)統(tǒng)計和限制
if (!position || !selectedRange) {
if (toBeString.length > 200) {
textView.text = [toBeString substringToIndex:200];
}
}
// 有高亮選擇的字符串,則暫不對文字進行統(tǒng)計和限制
else{
}
}
// 中文輸入法以外的直接對其統(tǒng)計限制即可,不考慮其他語種情況
else{
if (toBeString.length > 200) {
textView.text = [toBeString substringToIndex:200];
}
}
}
首先,我們根據(jù)鍵盤的輸入模式進行區(qū)分,英文的比較簡單就和上面一樣,直接取最大的字符數(shù)就好了,在中文輸入的時候,我們用markedTextRange方法獲取到當(dāng)前的光標位置,再用textField positionFromPosition:selectedRange.start offset:0獲取到高亮部分,然后判斷是否有高亮,這個時候系統(tǒng)會調(diào)用兩次通知方法,第一次是將高亮的字符輸入,第二次是將高亮的字符轉(zhuǎn)換成中文輸入(這個時候就沒有高亮了,然后再取最大的字符數(shù)),但是在iOS7的設(shè)備上測試時發(fā)現(xiàn),position都不會為nil,在iOS8以上都正常,但是獲取到光標的range,卻是正常的
NS_CLASS_AVAILABLE_IOS(3_2) @interface UITextRange : NSObject
@property (nonatomic, readonly, getter=isEmpty) BOOL empty;? ? //? Whether the range is zero-length.
@property (nonatomic, readonly) UITextPosition *start;
@property (nonatomic, readonly) UITextPosition *end;
@end
我們可以看到系統(tǒng)的UITextRange,有兩個變量,一個是start,一個是end,這正是對于的高亮區(qū)域!
所以既然position不能使用,那我們干脆就使用range,通過判斷range的存在,來對文字進行限制處理。(粘貼也適用)
結(jié)果也是棒棒的!