2016年07月26日星期二
今天同事问我,怎么比较优雅的限制UITextField的长度,我一拍脑袋,这好办啊。鼓捣了半天,发现答案和好的解决方案不是拍脑袋就能解决的。在这里讲讲我当时的心路历程。
首先,我决定用分类来实现限制UITextField的长度,这点在后来解决了之后,发现是没问题的。轻车熟路,的在分类中添加了个属性。什么?分类不能添加属性?这怎么能难住一个码畜喃。talk is cheap,show me the code.
@interface UITextField (MMTextLimteLong)
@property (nonatomic,assign) NSInteger textlong;
@end
static NSString *longkey = @"textlong";
-(NSInteger)textlong{
return [objc_getAssociatedObject(self, &longkey) integerValue] ;
}
-(void)setTextlong:(NSInteger)textlong{
objc_setAssociatedObject(self, &longkey, [NSString stringWithFormat:@"%ld",(long)textlong], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
稍微讲解一下顺便把关联也给科普了吧:
要使用关联必须使用<objc/runtime.h>的头文件,关联暂时只用得到三个方法
-(void)objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy);
//创建关联:参数设置(源对象,关键字,关联的对象和关联策略)
-(id)objc_getAssociatedObject(id object, void *key)
//获取关联对象:参数设置(源对象,关键字)
-(void)objc_removeAssociatedObjects(id object)
//断开所有关联,让“回到最初的起点”,也就是没有任何关联
//但是要断开部分关联的时候,可以用objc_setAssociatedObject,把关联对象传入nil就可以啦。
//上面写的"关键字",是一个void类型的指针,每个关联的关键字必须是唯一的。通常都是采用静态变量来作为关键字
//关联策略表明了相关的对象是通过赋值,保留引用还是赋值的方式进行关联的;
//还有这种关联是原子的还是非原子的。和属性的声明很类似。这种关联策略是通过使用预先定义好的常量来表示的。
上面鼓捣一大堆,不知道有没有看懂,反正我是在实践中用了才懂了一些的。上面的方法貌似官方的叫法是associative,是和category一起作为objective-c的扩展机制的两个特性。category既类型,可以通过它来扩展方法;associative,可以通过它来可扩展属性,不过看大神貌似用这个可以动态的设定方法,当然也可以动态的设定属性。以后再来把玩。
回到正题,用上面的方法鼓捣一阵后,在分类中声明好了属性。然后我最开始的思路是,用KVO去监听UITextField的text的改变。事实证明,我还是too🐑too森破。鼓捣了几个小时后,网友告诉我,UITextField的text是监听不到的。我也不知道能不能监听到,反正KVO一直给我说:你说的啥?我听不见。然后我又误入了另外一个企图。说出来又是一把辛酸泪。我在分类中实现了UITextField的代理方法。然后事情就解决了。但是,事情往往没有你想的那么简单。我在分类中实现了自己的代理方法,如果别人在外部要用UITextField的代理方法,我内部实现的代理方法就不能用了啊。代理方法只能有一个~~~~也是专一的让我流泪。后来突然想到了UIControlEventEditingChanged。这才算是走上了正路。
我在-(void)setTextlong:(NSInteger)textlong;方法中加入了
[self addTarget:self action:@selector(isChangelimite:) forControlEvents:UIControlEventEditingChanged];
-(void)isChangelimite:(UITextField *)textfield{
if (textfield.text.length >= self.textlong) {
NSRange range = NSMakeRange(0,self.textlong);
NSString *textfiledtext = textfield.text;
textfiledtext = [textfiledtext substringWithRange:range];
textfield.text = textfiledtext;
}
}
上面的方法,然后事情就解决了!
啊~世界是多么的美妙,空气是多麽的清新!