1. 內容字數限制
要限制一個UITextField的輸入字數,首先想到的應該是通過UITextFieldDelegate的代理方法來限制:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string; // return NO to not change text
比如要設置字數限制為20:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == self.titleField)
{
if (textField.length > 20) return NO;
}
return YES;
}
但是這樣的限制簡單粗暴,可能會影響用戶正常邏輯下的輸入,比如輸入了20個字符后,要退格回刪字符。
這時候我們可能會考慮“Detect backspace in UITextField”,比如簡單地判斷replacementString的長度是否為0。
接著我們可能還會遇到用戶已經輸入20個字符了,這時候繼續輸入---不過是選擇了部分文本進行替換-----無法進行了,這也妨礙了用戶的正常操作,所以限制的代碼版本可能會演進為:
#pragma mark - UITextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == self.titleField)
{
if (string.length == 0) return YES;
NSInteger existedLength = textField.text.length;
NSInteger selectedLength = range.length;
NSInteger replaceLength = string.length;
if (existedLength - selectedLength + replaceLength > 20) {
return NO;
}
}
return YES;
}
到這里可能會覺得基本大功告成了,但是當你輸入19個字符后,第20個字符以中文漢字的形式繼續輸入,那么系統會在鍵盤上方提供后續的一系列聯想詞,你會發現通過這種方式可以連續選字輸入從而突破20個字符的限制。WTF
到了這里,我們可能會希望有個類似
- (void)textFieldDidChange:(UITextField *)textField
的回調方法,但可惜沒有。
當然,我們還可以通過
- (void)textFieldDidEndEditing:(UITextField *)textField;
回調方法在結束編輯的時候把文本截斷,雖然在用戶體驗上會有點突兀。
不過當我們點進去UITextField.h頭文件里尋覓上述回調方法而不得時,可能會發現最下面有這么個消息通知名稱:
UIKIT_EXTERN NSString *const UITextFieldTextDidChangeNotification;
不過,監聽消息還要記得解除監聽,通常我還習慣把監聽消息的代碼統一放在一個方法中,看起來有點“大動干戈”。
所幸的是UITextField本身提供了相應的事件監聽:
[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
這樣就可以更好地限制輸入長度:
- (void)textFieldDidChange:(UITextField *)textField
{
if (textField == self.titleField)
{
if (textField.text.length > 20)
{
textField.text = [textField.text substringToIndex:20];
}
}
}