ios UITextfield輸入框限制:只能輸入兩位小數(shù)的價格格式或其他定制格式

前言

相信大家在ios移動應(yīng)用開發(fā)中报嵌,經(jīng)常會遇到這樣的需求:給輸入框限定輸入格式玻熙,比如最多只能輸入11個電話數(shù)字叉庐、只能輸入小于指定值的價格格式(同時最多兩位小數(shù))等等裹匙。我看了大家基本上是實(shí)現(xiàn)UITextFieldDelegate協(xié)議的textField:shouldChangeCharactersInRange:replacementString:方法瑞凑。但我發(fā)現(xiàn)很少對這種常見的需求實(shí)現(xiàn)進(jìn)行封裝。試想如果在開發(fā)中概页,一個view中有很多個UITextfield,而且還是需要不同的輸入格式要求籽御,那么我想在代理方法textField:shouldChangeCharactersInRange:replacementString:中的實(shí)現(xiàn)還是比較繁瑣的,需要各種判斷惰匙。

實(shí)現(xiàn)思路

為了解決上述問題技掏,我想封裝一個可以定制任何格式的UITextfileld 子類。
我準(zhǔn)備也在代理方法textField:shouldChangeCharactersInRange:replacementString:里面進(jìn)行字符判斷项鬼,來控制輸入框能否編輯哑梳。但為了更好的定制化,需要運(yùn)用不同的正則表達(dá)式來匹配格式绘盟。同時這些判斷邏輯我會寫在的UITextfileld子類 --- BSLimitFormTextFild里面鸠真。具體步驟如下:

  1. 創(chuàng)建UITextfileld子類BSLimitFormTextFild,添加正則表達(dá)式文本的屬性regex,用于控制各式各樣的輸入要求
    #import <UIKit/UIKit.h>

    static NSString *limitRegexPrice = @"^(\\d{0,5})(\\.[0-9]{0,2})?$"; // 最大值為         99999.99的價格正則表達(dá)式

    @interface BSLimitFormTextFild : UITextField

    @property (nonatomic, copy) NSString *regex; /**< 輸入框內(nèi)容的正則表達(dá)式 */


    @end

  1. 在BSLimitFormTextFild里面實(shí)現(xiàn)UITextfileld的代理方法textField:shouldChangeCharactersInRange:replacementString:龄毡,通過返回YES or NO來控制是否能夠輸入吠卷。
#import "BSLimitFormTextFild.h"
#import <objc/runtime.h>

@interface BSLimitFormTextFild() <UITextFieldDelegate>

@end
@implementation BSLimitFormTextFild

#pragma mark - Life Cycle && Initialize

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.delegate = self;
    }
    return self;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    self.delegate = self;
}

#pragma mark - private action

- (BOOL)predicateWithRegex:(NSString *)regex
                      text:(NSString *)text
                 textField:(UITextField *)textField {
    
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
    BOOL originMatch = YES;
    if (textField.text.length) {
        originMatch = [pred evaluateWithObject:textField.text];
    }
    if (originMatch) {
        //本來是符合規(guī)則的
        return [pred evaluateWithObject:text];
    }else{
        //本來不符合規(guī)則的話就清空(比如外部對該textFild set 一個不合規(guī)的text,當(dāng)點(diǎn)擊開始編輯時就要清空)
        textField.text = nil;
        return YES;
    }
}

#pragma mark - UITextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    NSString *toBeString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    if (!toBeString.length) {
        return YES;
    }
    if (self.regex) {
        return [self predicateWithRegex:self.regex text:toBeString textField:textField];
    } else {
        return YES;
    }
}

  1. 最后,可能在使用BSLimitFormTextFild的時候沦零,外部設(shè)置了delegate祭隔,比如用來監(jiān)聽UITextField的開始編輯、結(jié)束編輯的操作的話蠢终,這時會失效以上那些功能序攘;所以我重寫了- (void)setDelegate:(id<UITextFieldDelegate>)delegate 方法茴她,如果外部設(shè)置了新delegate,又沒有使用到textField:shouldChangeCharactersInRange:replacementString:方法的話,就自動給新代理動態(tài)添加該方法程奠,如果用到了就不做任何操作丈牢。具體代碼如下:

- (void)setDelegate:(id<UITextFieldDelegate>)delegate {
    [super setDelegate:delegate];
    if (delegate != self) {
        if (![delegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) {
            // 代理沒有實(shí)現(xiàn)該代理方法,就動態(tài)幫他實(shí)現(xiàn)
            // b表示反悔bool值; b@:表示沒有參數(shù);  b@:@表示有一個參數(shù)(文檔:https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html)
            class_addMethod(delegate.class, @selector(textField:shouldChangeCharactersInRange:replacementString:), class_getMethodImplementation(self.class, @selector(textField:shouldChangeCharactersInRange:replacementString:)), "b@:@:@:@");
        } else {
            // 外部實(shí)現(xiàn)了該代理方法瞄沙,就由外部決定是否可以編輯
        }
    }
}

demo演示


#import "ViewController.h"
#import "BSLimitFormTextFild.h"

@interface ViewController () <UITextFieldDelegate>

@property (weak, nonatomic) IBOutlet BSLimitFormTextFild *nomalTF;
@property (weak, nonatomic) IBOutlet BSLimitFormTextFild *priceTF;
@property (weak, nonatomic) IBOutlet BSLimitFormTextFild *integerTF;
@property (weak, nonatomic) IBOutlet BSLimitFormTextFild *limitCountTF;
@property (weak, nonatomic) IBOutlet BSLimitFormTextFild *customTF;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 只能輸入價格
    self.priceTF.regex = limitRegexPrice;
    // 只能輸入整數(shù)
    self.integerTF.regex = limitRegexInteger;
    // 最多只能輸入11位整數(shù)
    self.limitCountTF.regex = limitRegexIntegerCount;
    
    self.customTF.delegate = self;
}

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    NSString *toBeString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    if (toBeString.length > 2) {
        NSLog(@"最多只能輸入兩個字");
        return NO;
    } else {
        return YES;
    }
}

demo效果

結(jié)語

demo源碼我放在github上了https://github.com/LvBisheng/BSLimitFormTextFild和cocopods了(pod 'BSLimitFormTextFild', '~>1.0.0')己沛,歡迎大家指導(dǎo)交流...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市距境,隨后出現(xiàn)的幾起案子申尼,更是在濱河造成了極大的恐慌,老刑警劉巖垫桂,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件师幕,死亡現(xiàn)場離奇詭異,居然都是意外死亡诬滩,警方通過查閱死者的電腦和手機(jī)霹粥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疼鸟,“玉大人后控,你說我怎么就攤上這事】站担” “怎么了浩淘?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吴攒。 經(jīng)常有香客問我张抄,道長,這世上最難降的妖魔是什么舶斧? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任欣鳖,我火速辦了婚禮,結(jié)果婚禮上茴厉,老公的妹妹穿的比我還像新娘泽台。我一直安慰自己,他們只是感情好矾缓,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布怀酷。 她就那樣靜靜地躺著,像睡著了一般嗜闻。 火紅的嫁衣襯著肌膚如雪蜕依。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天,我揣著相機(jī)與錄音样眠,去河邊找鬼友瘤。 笑死,一個胖子當(dāng)著我的面吹牛檐束,可吹牛的內(nèi)容都是我干的辫秧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼被丧,長吁一口氣:“原來是場噩夢啊……” “哼盟戏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起甥桂,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤柿究,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后黄选,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蝇摸,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年糕簿,在試婚紗的時候發(fā)現(xiàn)自己被綠了探入。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狡孔。...
    茶點(diǎn)故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡懂诗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出苗膝,到底是詐尸還是另有隱情殃恒,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布辱揭,位于F島的核電站离唐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏问窃。R本人自食惡果不足惜亥鬓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望域庇。 院中可真熱鬧嵌戈,春花似錦、人聲如沸听皿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尉姨。三九已至庵朝,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背九府。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工椎瘟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人侄旬。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓降传,卻偏偏與公主長得像,于是被迫代替她去往敵國和親勾怒。 傳聞我的和親對象是個殘疾皇子婆排,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容