提出問題:
ios項(xiàng)目經(jīng)常遇到很多不同要求的textField, 比如這個(gè)要求只能輸入數(shù)字, 那個(gè)要求只能輸入英文字母....如果對每個(gè)textField實(shí)現(xiàn)delegate來判斷,代碼量過大. 有沒有簡化的方法?
方法步驟:
1.給UITextField新增一個(gè)屬性fieldType, 用于區(qū)別textField的輸入類型,就是通過Category, 新增一個(gè)動態(tài)關(guān)聯(lián)屬性(只能生成此屬性的set和get方法,不可生成對應(yīng)的成員變量_fieldType);
2.在APPdelegate中, 程序啟動時(shí), 給UITextField注冊兩個(gè)系統(tǒng)通知;
3.利用正則表達(dá)式, 限制輸入的字符(這里以"只能輸入數(shù)字"為例).
代碼實(shí)現(xiàn)
@interface UITextField (FieldType)
//增加一個(gè)文本類型的屬性(本質(zhì)是僅僅添加了set/get方法,不會增加成員變量)
@property (nonatomic,copy) NSString *fieldType;
@end
#import "UITextField+FieldType.h"
#import <objc/runtime.h>
@implementation UITextField (FieldType)
static const void *tagKey = &tagKey;//自定義的關(guān)聯(lián)標(biāo)識
//set方法
-(void)setFieldType:(NSString *)fieldType{
//給UITextField新增一個(gè)"fieldType"的關(guān)聯(lián)屬性
//(1)給誰新增方法; (2)關(guān)聯(lián)的唯一標(biāo)識; (3)屬性名; (4)關(guān)聯(lián)策略,如retain,copy等.
objc_setAssociatedObject(self, tagKey, fieldType, OBJC_ASSOCIATION_COPY_NONATOMIC);
// @param object The source object for the association.
// @param key The key for the association.
// @param value The value to associate with the key key for object. Pass nil to clear an existing association.
// @param policy The policy for the association.
}
//get方法
-(NSString *)fieldType{
//根據(jù)'關(guān)聯(lián)標(biāo)識', 返回關(guān)聯(lián)屬性
return objc_getAssociatedObject(self, tagKey);
}
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//程序一啟動, 就立馬注冊通知.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(beginEditingAction:) name:UITextFieldTextDidBeginEditingNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(infoAction:) name:UITextFieldTextDidChangeNotification object:nil];
return YES;
}
//第一個(gè)通知來得到我們開始編輯的TextField的原始值
-(void)beginEditingAction:(NSNotification *)notify{
UITextField *textField = (UITextField *)notify.object;
_textStr = textField.text;
}
//第二個(gè)通知來判斷我們輸入的字符串符不符合要求,我們首先需要一個(gè)通過正則表達(dá)式判斷是否符合規(guī)范的方法
-(void)infoAction:(NSNotification *)notify{
UITextField *textField = (UITextField *)notify.object ;
/*
_textStr為我們輸入字符串之前的TextField的值
**/
NSString *headStr = _textStr;
/**
判斷用戶是否進(jìn)行了刪除操作,如果進(jìn)行了刪除操作則該方法return
**/
if (textField.text.length < _textStr.length) {
_textStr = textField.text;
return;
}
/**
得到鍵入的字符串
**/
NSString *footStr = [textField.text substringFromIndex:_textStr.length];
/**
判斷該textField需要滿足校驗(yàn)
**/
if ([textField.fieldType isEqualToString:@"number"]) {
NSLog(@"此輸入框我們需要校驗(yàn)的類型!");
if ([self validateAccount:footStr]) {
/**
當(dāng)輸入的字符串符合規(guī)范時(shí)把新輸入的字符串添加到輸入框顯示的字符串中
**/
_textStr = [NSString stringWithFormat:@"%@%@",headStr,footStr];
}else{
/*
不符合規(guī)范時(shí)輸入框的內(nèi)容依然為我們輸入字符串之前的值
**/
textField.text = headStr;
}
}else {
NSLog(@"此輸入框不是我們想要的類型,不需要校驗(yàn)");
}
}
- (BOOL)validateAccount:(NSString *)textString{
NSString *number = @"^[0-9xX]+$";
NSPredicate *numberPre = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",number];
return [numberPre evaluateWithObject:textString];
}
<br>
動態(tài)關(guān)聯(lián)屬性, 指的是為某個(gè)類新增一個(gè)"關(guān)聯(lián)屬性", 與屬性的區(qū)別是不會生成一個(gè)_屬性名的成員變量. 所以,Category只能新增方法.