在第三方鍵盤加入之后,對于字數限制的處理不再像之前那么簡單了
純數字、字符輸入(不包括粘貼)這樣的字數限制還是相對比較簡單的,你可以用兩種方法進行處理
第一種是textfield的delegate實現:
- (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];
再實現通知里面的方法,在超過最大值時,取最大的字數
if (self.shopName.text.length > kMaxCharacterCount) {
self.shopName.text = [self.shopName.text substringToIndex:kMaxCharacterCount];
}
但是,在中文的限制上面情況就復雜了,當時在調試的時候,因為使用的是第三方鍵盤,所以當時沒有發現問題,但是在使用系統鍵盤的時候,一下子就蛋疼了….
下面我開始分析一下,兩者的區別:1、第三方鍵盤在輸入字符時,一般是不會將字符直接輸入到textfield中,而是將字符顯示在它自己的view上方,但是系統鍵盤會直接輸入到textfield中,而且它會占2個字符長度,比如你輸入”abcd”,在textfield中顯示的是”a b c d”,并且”a b c d”是處在高亮中的,并不算是真正輸入到textfield中,所以我們不應把高亮的字符計算在內,我們應該計算真正輸入的字符
2、如果我們使用的是delegate做處理的時候,系統中文輸入的時候會有聯想,但是聯想的那個字并不會調用delegate,比如你輸入一個”你”,在系統的聯想里面可能會出現”的”,”們”這樣的聯想,但是你選擇”的”的時候,delegate并不會調用,(尼瑪….),我猜想聯想輸入應該不算做keyboard所觸發的事件,所以他并不會觸發delegate,但是如果你注冊的是通知,他倒是會調用,(還好有救)
另外提醒一下,有時候在自測輸入的時候,要考慮全面,比如粘貼這也是一種輸入,當時沒考慮,我也是跪了
好了,分析了主要的區別下面我們就來看看具體怎么實現吧~
在實現注冊通知方法里面:
#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];
// 沒有高亮選擇的字,則對已輸入的文字進行字數統計和限制
if (!position || !selectedRange) {
if (toBeString.length > 200) {
textView.text = [toBeString substringToIndex:200];
}
}
// 有高亮選擇的字符串,則暫不對文字進行統計和限制
else{
}
}
// 中文輸入法以外的直接對其統計限制即可,不考慮其他語種情況
else{
if (toBeString.length > 200) {
textView.text = [toBeString substringToIndex:200];
}
}
}
首先,我們根據鍵盤的輸入模式進行區分,英文的比較簡單就和上面一樣,直接取最大的字符數就好了,在中文輸入的時候,我們用markedTextRange方法獲取到當前的光標位置,再用textField positionFromPosition:selectedRange.start offset:0獲取到高亮部分,然后判斷是否有高亮,這個時候系統會調用兩次通知方法,第一次是將高亮的字符輸入,第二次是將高亮的字符轉換成中文輸入(這個時候就沒有高亮了,然后再取最大的字符數),但是在iOS7的設備上測試時發現,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
我們可以看到系統的UITextRange,有兩個變量,一個是start,一個是end,這正是對于的高亮區域!
所以既然position不能使用,那我們干脆就使用range,通過判斷range的存在,來對文字進行限制處理。(粘貼也適用)
結果也是棒棒的!