限制 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,这么做实现了咱们的需求,在各种输入法、中英文下都运行无误。这就完了?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

代码在 这里 。


嗯,简单直接,就是它了!


0 0