UITextView UITextField 輸入字?jǐn)?shù)限制

UITextView和UITextField沒(méi)有自帶的輸入字?jǐn)?shù)限制功能膊毁。
如果需要實(shí)現(xiàn)這個(gè)功能,一般的做法有兩種基跑,delegate和監(jiān)控Notification婚温。

先看看UITextViewDelegate,UITextField也是類似的媳否。

@protocol UITextViewDelegate <NSObject, UIScrollViewDelegate>

@optional

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView;
- (BOOL)textViewShouldEndEditing:(UITextView *)textView;

- (void)textViewDidBeginEditing:(UITextView *)textView;
- (void)textViewDidEndEditing:(UITextView *)textView;

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
- (void)textViewDidChange:(UITextView *)textView;

- (void)textViewDidChangeSelection:(UITextView *)textView;

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction NS_AVAILABLE_IOS(10_0);
- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction NS_AVAILABLE_IOS(10_0);

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithURL:inRange:forInteractionType: instead");
- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment:(NSTextAttachment *)textAttachment inRange:(NSRange)characterRange NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithTextAttachment:inRange:forInteractionType: instead");

@end

初步來(lái)看栅螟,會(huì)選用以下這兩個(gè)回調(diào)方法做處理。

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
- (void)textViewDidChange:(UITextView *)textView;

選了第一個(gè)篱竭,以下的代碼力图,在iOS 10上運(yùn)行,沒(méi)問(wèn)題掺逼,so easy~~~

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    if (textView.text.length + text.length > kLimitCount) {
        NSLog(@"%@",[NSString stringWithFormat:@"最高支持輸入%d個(gè)字",kLimitCount]);
        if (textView.text.length > 0) {
            [self.textViewTipsLabel setHidden:YES];
        } else {
            [self.textViewTipsLabel setHidden:NO];
        }
        return NO;
    }
    return YES;
}

但是too young too sample吃媒,在iOS 9上出問(wèn)題了,如果使用iOS 9輸入中文吕喘,在選擇中文時(shí)赘那,不會(huì)調(diào)用shouldChangeTextInRange的回調(diào)。
呵呵~~~ 這個(gè)應(yīng)該是apple的問(wèn)題吧兽泄,有問(wèn)題就要解決啊漓概,所以同時(shí)需要在textViewDidChange中也需要做處理。

- (void)textViewDidChange:(UITextView *)textView {
    if (textView.text.length > kLimitCount) {
        // 超出限制
        textView.text = [textView.text substringToIndex:kLimitCount];
        NSLog(@"%@",[NSString stringWithFormat:@"最高支持輸入%d個(gè)字",kLimitCount]);
    }
    
    if (textView.text.length > 0) {
        [self.textViewTipsLabel setHidden:YES];
    } else {
        [self.textViewTipsLabel setHidden:NO];
    }
}

textViewTipsLabel是一個(gè)提示的label病梢,因?yàn)閁ITextView沒(méi)有placeholder胃珍。

OK,大概的解決方案就完整了蜓陌,如果工程中大量用到UITextView UITextField 輸入字?jǐn)?shù)限制觅彰,可以寫一個(gè)分類實(shí)現(xiàn),(不推薦使用繼承的方式)

分類中監(jiān)控自己的delegate顯然不是很好(自己回調(diào)自己钮热,然后又要回調(diào)出去)填抬。所以考慮用NSNotificationCenter。UITextView相關(guān)的Notification隧期,有以下幾個(gè)飒责,

UIKIT_EXTERN NSNotificationName const UITextViewTextDidBeginEditingNotification;
UIKIT_EXTERN NSNotificationName const UITextViewTextDidChangeNotification;
UIKIT_EXTERN NSNotificationName const UITextViewTextDidEndEditingNotification;

UITextView的分類UITextView+InputLimit只能監(jiān)控UITextViewTextDidChangeNotification了。
同時(shí)分類中增加兩個(gè)屬性(分類是可以增加屬性的仆潮,具體的方法網(wǎng)上很多)宏蛉。
inputLimit_placeholderLabel:占位的label,做提示用性置,可以不顯示拾并。
inputLimit_limitCount:現(xiàn)在字符長(zhǎng)度,方便使用。
外部類只需要關(guān)系這兩個(gè)屬性就好了嗅义,在設(shè)置屬性時(shí)或做相應(yīng)的處理屏歹,
以下是部分關(guān)鍵代碼:

- (void)setInputLimit_placeholderLabel:(UILabel *)inputLimit_placeholderLabel {
    if (!inputLimit_placeholderLabel && inputLimit_placeholderLabel != self.inputLimit_placeholderLabel) {
        // 移除舊的placeholderLabel
        [self.inputLimit_placeholderLabel removeFromSuperview];
        // 添加新的
        [self addSubview:inputLimit_placeholderLabel];
        objc_setAssociatedObject(self, PlaceholderLabelKey, inputLimit_placeholderLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
}

- (void)setInputLimit_limitCount:(NSUInteger)inputLimit_limitCount {
    if (inputLimit_limitCount == self.inputLimit_limitCount) {
        return;
    }
    if (self.inputLimit_limitCount == 0 && inputLimit_limitCount > 0) {
        // 從0到不是0,需要注冊(cè)通知
        [self addInputLimit];
    }
    if (inputLimit_limitCount == 0) {
        // limitCount為0之碗,不需要監(jiān)控了
        [self removeInputLimit];
    }
    objc_setAssociatedObject(self, LimitCountKey, @(inputLimit_limitCount), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(void)textViewDidChange:(NSNotification *)notification {
    
#if DEBUG
    NSCAssert(self.inputLimit_limitCount > 0, @"監(jiān)控了UITextViewTextDidChangeNotification的消息蝙眶,但是沒(méi)有設(shè)置limitCount的大小");
#endif
    
    UITextView *textView = (UITextView *)notification.object;
    
    // 不是當(dāng)前textView和沒(méi)有限制limitCount時(shí),不做處理
    if (textView == self && self.inputLimit_limitCount != 0) {
        if (textView.text.length > self.inputLimit_limitCount) {
            // 超出限制
            textView.text = [textView.text substringToIndex:self.inputLimit_limitCount];
            // 發(fā)送消息
            [[NSNotificationCenter defaultCenter] postNotificationName:UITextViewInputLimitBeyondNotification object:self];
            #if DEBUG
            NSLog(@"%@",[NSString stringWithFormat:@"最高支持輸入%lu個(gè)字",(unsigned long)self.inputLimit_limitCount]);
            #endif
        }
        
        if (textView.text.length > 0) {
            [self.inputLimit_placeholderLabel setHidden:YES];
        } else {
            [self.inputLimit_placeholderLabel setHidden:NO];
        }
    }
    
}

好继控,到這里械馆,基本已經(jīng)完事了。這里有一點(diǎn)一開始很困惑就是分類中在設(shè)置字符長(zhǎng)度注冊(cè)(addObserver)了NSNotificationCenter武通,必須有個(gè)地方需要移除(removeObserver)霹崎。如果不移除,UITextView釋放時(shí)候冶忱,NSNotificationCenter發(fā)送通知會(huì)不會(huì)造成崩潰尾菇。
有驗(yàn)證過(guò)在ARC的環(huán)境下(現(xiàn)在都是ARC的代碼了吧。囚枪。派诬。)不需要移除。原因是UITextView本身的dealloc链沼,
會(huì)調(diào)用removeObserver的方法默赂。具體的驗(yàn)證這里不細(xì)講了。
如果要移除可以考慮重寫分類中的dealloc括勺,這樣比較麻煩需要在load函數(shù)中把方法替換缆八。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市疾捍,隨后出現(xiàn)的幾起案子奈辰,更是在濱河造成了極大的恐慌,老刑警劉巖乱豆,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奖恰,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡宛裕,警方通過(guò)查閱死者的電腦和手機(jī)瑟啃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)揩尸,“玉大人蛹屿,你說(shuō)我怎么就攤上這事∑W茫” “怎么了蜡峰?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)朗恳。 經(jīng)常有香客問(wèn)我湿颅,道長(zhǎng),這世上最難降的妖魔是什么粥诫? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任油航,我火速辦了婚禮,結(jié)果婚禮上怀浆,老公的妹妹穿的比我還像新娘谊囚。我一直安慰自己,他們只是感情好执赡,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布镰踏。 她就那樣靜靜地躺著,像睡著了一般沙合。 火紅的嫁衣襯著肌膚如雪奠伪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天首懈,我揣著相機(jī)與錄音绊率,去河邊找鬼。 笑死究履,一個(gè)胖子當(dāng)著我的面吹牛滤否,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播最仑,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼藐俺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼墩新!你這毒婦竟也來(lái)了趴捅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤田柔,失蹤者是張志新(化名)和其女友劉穎全景,沒(méi)想到半個(gè)月后耀石,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡爸黄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年滞伟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炕贵。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡梆奈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出称开,到底是詐尸還是另有隱情亩钟,我是刑警寧澤乓梨,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站清酥,受9級(jí)特大地震影響扶镀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜焰轻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一臭觉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧辱志,春花似錦蝠筑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至已球,卻和暖如春稳强,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背和悦。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工退疫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鸽素。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓褒繁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親馍忽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子棒坏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

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

  • 原文鏈接http://www.cnblogs.com/kenshincui/p/4186022.html 音頻在i...
    Hyman0819閱讀 21,720評(píng)論 4 74
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)磨澡、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,117評(píng)論 4 61
  • 我覺(jué)得我進(jìn)入了人生的困境质和。 這和初高中是不同的稳摄,不是我只要努力努力就可以擺脫的困擾。我發(fā)現(xiàn)饲宿,我一直具有的人生進(jìn)取的...
    秘耳閱讀 273評(píng)論 0 0
  • 我對(duì)你做了一道選擇題 原以為有50%的正確率 到頭來(lái)才發(fā)現(xiàn)是0%…… 不管怎么樣 都是錯(cuò)的
    霂淰閱讀 163評(píng)論 0 0
  • 最近生活的關(guān)注點(diǎn)不在此處厦酬。突然想進(jìn)行點(diǎn)回憶胆描。 小時(shí)候特別迷信術(shù)。當(dāng)然仗阅,那個(gè)時(shí)候不知道啥是術(shù)袄友。只是故事看多了,覺(jué)得總...
    mylkevin閱讀 238評(píng)論 0 0