三種方法探究UITextField的text長度限制與判斷

開發(fā)過程中會經(jīng)常遇到各種優(yōu)化性的需求喉钢,比如對輸入控件的一些限制性操作。如:限制UITextField的輸入長度良姆。
關(guān)于英文肠虽、數(shù)字、中文玛追、emoji中每個字符所占的長度不同税课。根據(jù)需求的不同,自己進(jìn)行計算豹缀。本文不做贅述伯复。
[需要注意的是:限制的總長度 - 現(xiàn)有的總長度 > 本次輸入長度慨代。那么本次輸入不會成功邢笙。]

本文共提供三類方法來解決這種需求(三個方法用于用戶輸入,一個方法用于代碼賦值)


UITextFieldDelegate

從系統(tǒng)提供的textField的方法里面進(jìn)行查找
在UITextFieldDelegate里面通過// return NO to not change text這條注釋找到了這么一個方法:

  • (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
    // return NO to not change text

可以看出這個方法是系統(tǒng)提供的控制UITextField的text這個屬性的方法侍匙。而字符限制的輸入本質(zhì)上是更改其輸入的文本信息氮惯。

這個實例方法有三個參數(shù)```textfield```、```range```想暗、```string```妇汗。分別表示當(dāng)前相應(yīng)的textfield,當(dāng)前已經(jīng)顯示的字符被更改的范圍说莫,要更改的內(nèi)容杨箭。以及一個```BOOL```類型的返回值來控制是否執(zhí)行本次更改。

  • (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString )string
    { //
    kMaxLimit的值為你限制輸入的字符數(shù) */
    if (range.location == kMaxLimit && range.length == 0) {
    // textField.text = [textField.text substringToIndex:kMaxLimit];
    // 當(dāng)返回NO的情況下已經(jīng)不會輸入本次內(nèi)容了储狭』バ觯可以進(jìn)行測試捣郊,下文會給出原因。
    return NO;
    }
    return YES;
    }
通過這個方法已經(jīng)能控制鍵入的字符長度了慈参。但是呛牲,用戶這個時候是可以通過粘貼這個功能輸入超過我們限制條件的情況的。如果用戶通過粘貼來輸入驮配,還是能夠放入我們超出我們限制條件的內(nèi)容娘扩。可以通過增加邏輯判斷來解決:
  • (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    NSUInteger maxLimit = 9; // 模擬長度為9的情況.
    if (range.location == maxLimit && range.length == 0) { // 限制了輸入時候的情況
    return NO;
    }
    if (range.location < maxLimit && (string.length + range.location) > maxLimit) { // 限制了粘貼字符時候的情況
    return NO;
    }
    return YES;
    }
這個時候就解決了用戶輸入(鍵入壮锻、粘貼)時的字符長度限制琐旁。

***
###Target Action機(jī)制
因為UITextField繼承于UIControl類,那么同樣可以重載父類方法來實現(xiàn)這種需求猜绣。需要注意的是最后一個參數(shù)旋膳,在枚舉值中選取的是`UIControlEventEditingChanged`這種情況。

[textFieldObject addTarget:self action:@selector(textFieldCharacterChange:) forControlEvents:UIControlEventEditingChanged];


  • (void)textFieldCharacterChange:(UITextField *)textField
    {
    if (textField.text.length > 11) {
    textField.text = [textField.text substringToIndex:11];
    }
    }
這樣一個判斷就可以在用戶操作的時候( 鍵入途事、粘貼) 進(jìn)行字符長度限制了验懊。
***
###觀察者模式
在TextField的API里面,系統(tǒng)提供了幾種監(jiān)聽的屬性.根據(jù)時機(jī)與作用選取第三個尸变。`UITextFieldTextDidChangeNotification`

>`UIKIT_EXTERN NSNotificationName const UITextFieldTextDidBeginEditingNotification;`
>`UIKIT_EXTERN NSNotificationName const UITextFieldTextDidEndEditingNotification;`
>`UIKIT_EXTERN NSNotificationName const UITextFieldTextDidChangeNotification;`

代碼如下:

if ([self respondsToSelector:@selector(test:)]) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test:) name:UITextFieldTextDidChangeNotification object:nil];
}

  • (void)test:(NSNotification *)notification {
    UITextField *tf = notification.object;
    if (tf.text.length > 10) {
    tf.text = [tf.text substringToIndex:10];
    }
    }

  • (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];
    }

這個時候做測試义图,會發(fā)現(xiàn)能監(jiān)聽到響應(yīng)用戶的操作,但是同樣監(jiān)聽不到代碼的賦值操作召烂。
***
如果需要先對UITextFIeld賦值(比如用戶修改個人信息的時候)碱工,如果因為某些原因,字符長度超出了預(yù)期奏夫,那么就容易引起用戶誤解怕篷。代碼賦值可以使用KVO進(jìn)行監(jiān)聽,代碼如下:

[_textField addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:nil];

  • (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    UITextField *tf = object;
    if (tf.text.length > 10) {
    tf.text = [tf.text substringToIndex:10];
    }
    }

  • (void)dealloc {
    [_textField removeObserver:self forKeyPath:@"text"];
    }

這時候會發(fā)現(xiàn)酗昼,此時的監(jiān)聽只能監(jiān)聽到代碼對text進(jìn)行的賦值操作廊谓,不能監(jiān)聽到用戶輸入的操作。剛好和上面的方法在作用區(qū)域上互補(bǔ)麻削。

***
關(guān)于上述的方法:
一蒸痹、UITextFieldDelegate里提供的方法,能夠處理掉用戶鍵入的操作呛哟。但是當(dāng)用戶采用粘貼的形式輸入內(nèi)容的時候叠荠,會出現(xiàn)不可預(yù)知的bug。API里最適合處理這個需求的方法扫责,但是需要大量的邏輯判斷來滿足需求榛鼎。
二、通過對UITextField的父類逐級上查,發(fā)現(xiàn)其可以使用TargetAction機(jī)制進(jìn)行通信與監(jiān)測者娱。這個方法使用簡單蜘渣,邏輯上易懂。(個人喜歡用這一種)
三肺然、觀察者模式蔫缸。`UITextFieldTextDidChangeNotification `是對用戶操作的相應(yīng)于監(jiān)聽;`KVO`是對代碼賦值時的監(jiān)聽际起。

***
以上內(nèi)容為如有紕漏拾碌,還請指出交流。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末街望,一起剝皮案震驚了整個濱河市校翔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件于微,死亡現(xiàn)場離奇詭異唯沮,居然都是意外死亡仔涩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人奈嘿,你說我怎么就攤上這事⊥碳樱” “怎么了裙犹?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長衔憨。 經(jīng)常有香客問我叶圃,道長,這世上最難降的妖魔是什么践图? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任掺冠,我火速辦了婚禮,結(jié)果婚禮上平项,老公的妹妹穿的比我還像新娘赫舒。我一直安慰自己,他們只是感情好闽瓢,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著心赶,像睡著了一般扣讼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上缨叫,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天椭符,我揣著相機(jī)與錄音荔燎,去河邊找鬼。 笑死销钝,一個胖子當(dāng)著我的面吹牛有咨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蒸健,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼座享,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了似忧?” 一聲冷哼從身側(cè)響起渣叛,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盯捌,沒想到半個月后淳衙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡饺著,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年箫攀,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幼衰。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡匠童,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出塑顺,到底是詐尸還是另有隱情汤求,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布严拒,位于F島的核電站扬绪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏裤唠。R本人自食惡果不足惜挤牛,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望种蘸。 院中可真熱鬧墓赴,春花似錦、人聲如沸航瞭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刊侯。三九已至章办,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背藕届。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工挪蹭, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人休偶。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓梁厉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親踏兜。 傳聞我的和親對象是個殘疾皇子词顾,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

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