在網路上爬了許多限制UITextField輸入文字的方法,

其中一種是使用textfield delegate裡的shouldChangeCharactersInRange方法,

若按鍵盤上方quick type中的文字來輸入的話,

這個方法就會失效,並且用注音輸入中文字時會有諸多問題。

最後解決方法如下:

先在textField加入一個方法textFieldDidChange:

[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];

實做textFieldDidChange:方法

- (void)textFieldDidChange:(UITextField *)textField {
 
 NSInteger maxStringLength = 20;
 NSString *aString = textField.text;
 NSString *lang = [textField.textInputMode primaryLanguage];// 鍵盤輸入模式
 if ([lang isEqualToString:@"zh-Hans"] || [lang isEqualToString:@"zh-Hant"]) { // 中文輸入,包括繁體zh-Hant與簡體zh-Hans
 UITextRange *selectedRange = [textField markedTextRange];
 // 獲取被選取的文字區域(在打注音時,還沒選字以前注音會被選起來)
 UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
 // 沒有被選取的字才限制文字的輸入字數
 if (!position) {
 if (aString.length > maxStringLength) {
 textField.text = [aString substringToIndex:maxStringLength];
 }
 }
 
 } else {
 // 其他字體不判斷直接限制字數
 if (aString.length > maxStringLength) {
 textField.text = [aString substringToIndex:maxStringLength];
 }
 }
}

這個方法主要是忽略還沒打完而被選起來的字,
就能得到實際輸入的字的長度。

2016/03/02 更新:
後來得知似乎除了中文,
韓文與日文輸入似乎也會有同樣的問題,
而其他直接輸入的語言又不會有被選起來的問題(如英文是每個字母直接打上去),
所以其實這段code可以在精簡成:

- (void)textFieldDidChange:(UITextField *)textField {
 
 NSInteger maxStringLength = 20;
 NSString *aString = textField.text;
 UITextRange *selectedRange = [textField markedTextRange];
 // 獲取被選取的文字區域(在打注音時,還沒選字以前注音會被選起來)
 UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
 // 沒有被選取的字才限制文字的輸入字數
 if (!position) {
 if (aString.length > maxStringLength) {
 textField.text = [aString substringToIndex:maxStringLength];
 }
 }
}

如此一來這個判斷對任何語系都適用了!