如果我们的产品需求对我们的输入做了很多的限制,那么就需要我们在每一个的textField的View中都要做各种限制,太过于麻烦。
我通过写一个类别,来统一处理这种情况,一个方法就可以直接调用,并检测textField中的数据变化。现在只是写完了,还没有全方位的测试。
.h文件
typedef NS_ENUM(NSUInteger, UITextFieldLimitType) {
UITextFieldLimitTypeNoneSpecial = 1, //无特殊处理
UITextFieldLimitTypeCountChar = 2, //仅数字加字符
UITextFieldLimitTypeInputName = 3, //可输入正常无表情
UITextFieldLimitTypeOnlyLimitCharCount = 4, //仅限制数字
};
typedef void(^TextValue)(NSString *text,UITextField *textField);
@interface UITextField (Limit)
@property (assign, nonatomic) NSInteger limitCount;
@property (assign, nonatomic) UITextFieldLimitType limitType;
//@property (strong, nonatomic) NSString *lastText;
@property (copy, nonatomic) TextValue textValue;
- (void)setLimitType:(UITextFieldLimitType)limitType limitCount:(NSInteger)limitCount;
.m文件
通过runtime将重写set get方法 #import <objc/runtime.h>
static char limitCountKey;
- (long)limitCount{
return [objc_getAssociatedObject(self, &limitCountKey) integerValue];
}
- (void)setLimitCount:(NSInteger)limitCount{
if (limitCount != self.limitCount) {
[self willChangeValueForKey:@"limitCount"];
objc_setAssociatedObject(self, &limitCountKey,[NSNumber numberWithInteger:limitCount], OBJC_ASSOCIATION_ASSIGN);
[self didChangeValueForKey:@"limitCount"];
}
}
通过调用限制方法来监听输入框的变化
- (void)setLimitType:(UITextFieldLimitType)limitType limitCount:(NSInteger)limitCount{
self.limitType = limitType;
self.limitCount = limitCount;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textViewEditChanged:)
name:UITextFieldTextDidChangeNotification
object:nil];
}
这里有一些正则表达式需要根据自己的需求去写
-(void)textViewEditChanged:(NSNotification *)notification{
// 拿到文本改变的 text field
UITextField *textField = (UITextField *)notification.object;
if (textField != self) {
return;
}
if (textField.markedTextRange) {
return;
}
// 没有高亮内容时,对已输入的文字进行操作
NSString *inputText = textField.text;
switch (self.limitType) {
case UITextFieldLimitTypeNoneSpecial:{
// 不做处理
}
break;
case UITextFieldLimitTypeCountChar:{
NSString *legalStr = @"";
for(int i =0; i < [inputText length]; i++){
NSString *temp = [inputText substringWithRange:NSMakeRange(i, 1)];
if ([temp isValidateCountChar]) {
legalStr = [legalStr stringByAppendingString:temp];
}
}
inputText = legalStr;
}
break;
case UITextFieldLimitTypeInputName:{
NSString *legalStr = @"";
for(int i =0; i < [inputText length]; i++){
NSString *temp = [inputText substringWithRange:NSMakeRange(i, 1)];
if ([self canInput:textField string:temp]) {
legalStr = [legalStr stringByAppendingString:temp];
}
}
inputText = legalStr;
}
break;
case UITextFieldLimitTypeOnlyLimitCharCount:{
NSString *legalStr = @"";
for(int i =0; i < [inputText length]; i++){
NSString *temp = [inputText substringWithRange:NSMakeRange(i, 1)];
if ([temp isValiCount]) {
legalStr = [legalStr stringByAppendingString:temp];
}
}
inputText = legalStr;
}
break;
default:
break;
}
textField.text = inputText;
// text field 的内容
NSString *contentText = textField.text;
if (self.limitCount > 0) {
// 如果 text field 的内容长度大于我们限制的内容长度
if (contentText.length > self.limitCount) {
NSRange rangeRange = [contentText rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, self.limitCount)];
textField.text = [contentText substringWithRange:rangeRange];
}
}
if (self.textValue) {
self.textValue(textField.text,textField);
}
}
- (BOOL)canInput:(UITextField *)textField string:(NSString *)string{
if ([textField isFirstResponder]) {
if ([[[textField textInputMode] primaryLanguage] isEqualToString:@"emoji"] || ![[textField textInputMode] primaryLanguage]) {
return NO;
}
//判断键盘是不是九宫格键盘
if ([string isNineKeyBoard] ){
return YES;
}else{
if ([string hasEmoji] || [string stringContainsEmoji]){
return NO;
}
}
}
return YES;
}
最后在dealloc方法中移除监听的通知。
- (void)dealloc{
// 移除事件的监听。注意这里的前提是我们的textfield都是全局的变量。
// 局部变量会在当前的方法走完后就执行了这个方法,导致无法继续监听。
}