限制 UITextField 輸入長度,uitextfield長度
限制 UITextField 輸入長度
標籤(空格分隔): UITextField
UITextField 是 iOS 中最常用的組件之一。關於它也有各種各樣的需求,這些需求是它本身沒有提供相應的API的。限制輸入框文本長度是常見的需求,UITextField 本身也並沒有為此提供API。本文嘗試給其加入這個功能。
1、通過 delegate 來實現(不推薦)
限制 UITextField 的輸入字數,首先想到的是 UITextFieldDelegate,通過實現這個協議來實現需求:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string; // 返回 NO 就不會改變文本
OK,那咱們來試試看:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSString *beString = [textField.text stringByReplacingCharactersInRange:range withString:string]; if ([beString length] > 20) { textField.text = [beString substringToIndex:20]; return NO; } return YES;}
1. 先計算出在使用者輸入這段文字會產生的新文本:beString。
2. 再判斷beString長度是否符合長度限制(這裡為20)。
3. 如果符合則返回YES,否則返回NO。
OK,這麼做實現了咱們的需求,在各種IME、中英文下都運行無誤。這就完了?NO!
我們來說說這種解決文案的不足之處:
1. 代碼量太多。看看上面的例子,這還是只是一個輸入框,如果有2個、3個、N個。。。 (這得重新考慮一下你們的需求了)
2. 給每一個要限制長度的輸入框都得這麼寫,想想也是醉了(沒錯,偶以前也是這麼乾的)。
2、繼承 UITextField來實現(不推薦)
繼承 UITextField ,覆寫 setText: 方法應該是可以實現的(偶沒做過)。但基於無數先輩們得出的經驗:組合先於繼承。在這裡用繼承也是有點小問題的:假設咱們子類名字為 NLUITextFieldTextLimit,那 NITextField(nimbus 架構中的一個類) 對象也就無法享受到這一服務了。
3、分類添加屬性來實現(推薦)
如果能用分類,添加一個屬性來實現這個需求得多爽呀,在 UITextField 中定義一個屬性就好了。咱們來研究一下 UITextField 看看有沒有可能。
@interface UITextField : UIControl...
UITextField 是繼承自 UIControl 的,那它可以監聽自身的事件咯!Good!我們只要得知其輸入文本變化後,再判斷長度是否符合需求。看看咱們的代碼:
// .h file@interface UITextField (NLLimit)@property (assign, nonatomic) NSUInteger nl_maxLength;@end// .m file#import <objc/runtime.h>@implementation UITextField (NLLimit)static void *nlLimitMaxLengthKey = &nlLimitMaxLengthKey;- (void)setNl_maxLength:(NSUInteger)nl_maxLength { objc_setAssociatedObject(self, nlLimitMaxLengthKey, @(nl_maxLength), OBJC_ASSOCIATION_COPY); /** * 監控自身文本變化 */ if (nl_maxLength > 0) { [self addTarget:self action:@selector(_nl_valueChanged:) forControlEvents:UIControlEventAllEditingEvents]; } else { [self removeTarget:self action:@selector(_nl_valueChanged:) forControlEvents:UIControlEventAllEditingEvents]; }}- (NSUInteger)nl_maxLength { return [objc_getAssociatedObject(self, nlLimitMaxLengthKey) unsignedIntegerValue];}#pragma mark - private- (void)_nl_valueChanged:(UITextField *)textField { /** * 在文本變化後判斷文本長度是否符合需求 */ if (self.nl_maxLength == 0) return; if ([textField.text length] <= self.nl_maxLength) return; NSString *subString = [textField.text substringToIndex:self.nl_maxLength]; dispatch_async(dispatch_get_main_queue(), ^{ textField.text = subString; [textField sendActionsForControlEvents:UIControlEventEditingChanged]; });}@end
代碼在這裡。
嗯,簡單直接,就是它了!
4、限制 UITextView 輸入長度
在 UITextField 中我們推薦的限制文本長度的方式是通過分類中添加屬性來做到的,其本質是監控自身的輸入文本變化,再判斷長度是否符合需求。那 UITextView 是不是也可以這麼做呢?
@interface UITextView : UIScrollView
可惜的是,正如上面所示,UITextView 是 UIScrollView 的子類,並非如 UITextField 那般是 UIControl 的子類,也就是說 UITextView 無法像 UITextField 那樣通過監控自身的來達到限制的目的了。
不過好在我們在 UITextView 的說明文檔中看到了幾個通知:
NSString * const UITextViewTextDidBeginEditingNotification;NSString * const UITextViewTextDidChangeNotification;NSString * const UITextViewTextDidEndEditingNotification;
通過這幾個通知也可以得知任何一個 UITextView 輸入文本的變化了。咱們可以整個輔助類來做到這一點。代碼就不貼出來了,你也可以自己實驗一下,想看完整代碼,在這裡。