iOS UITextField輸入限制(中英文混合)

先說說記錄這個的原因吧威始,關于限制UITextField的輸入字數(shù)的各種需求,已經(jīng)疲軟了像街,工作幾年中用的還真不少黎棠,有只要字數(shù)長度的,也有字符長度的镰绎,當然這個就包括中文和英文葫掉,還有.....標點符號也分中文和英文的,每次都多不情愿的寫這個地方跟狱,閑來無事俭厚,就來記錄一下,方便大家驶臊,若有不對的地方挪挤,多多指教哈。

關于UITextField

大家肯定對下面這個方法非常熟悉

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

那么這個函數(shù)的大概意思是什么呢关翎?我是這么理解的(個人認為)
由于返回的是個 BOOL 所以我猜想大概就是我們在輸入的時候扛门,是否對UITextField 的內(nèi)容進行修改
下面來簡單分析下參數(shù)
textField 這個參數(shù)大家都懂,就是響應該協(xié)議的UITextField對象
range在這個函數(shù)中纵寝,添加了打印信息论寨,測試了下

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
        NSLog(@" 打印信息:%lu  -----%lu ",(unsigned long)range.location,(unsigned long)range.length);
}

//打印log
2017-01-25 17:48:49.826 TestObject[5502:683375]  打印信息toBeString:Zxtgfd
2017-01-25 17:48:50.506 TestObject[5502:683375]  打印信息:6  -----0 
2017-01-25 17:48:50.508 TestObject[5502:683375]  打印信息toBeString:Zxtgfda
2017-01-25 17:48:51.894 TestObject[5502:683375]  打印信息:6  -----1 

由此可以看到,在輸入的時候爽茴,range.length為0葬凳,range.location為插入時的位置 ,range.length為1時室奏,是我在點擊刪除的時候打印的火焰,應該可以表示刪除(不確定)
string string.length為0時,表示刪除胧沫。

限制輸入長度
  • 1 如果只是輸入英文狀態(tài)昌简,或者數(shù)字狀態(tài)占业,那么我們我們可以利用這個函數(shù),實現(xiàn)方法為:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    
        NSLog(@" 打印信息:%lu  -----%lu ",(unsigned long)range.location,(unsigned long)range.length);
    
    if (textField.text.length + string.length > kMaxNumber) {
        
        return NO;
    }
    
    //刪除按鈕
    if (string.length == 0)
    {
        return YES;
    }
    
    return YES;
}
  • 2 但是纯赎,如果要涉及到中文的話谦疾,這樣就不行了。因為犬金,在輸入中文的時候念恍,如果你還沒有確定所輸入的中文,那么UITextField此時接收的并不是中文佑附,而是對應的拼音樊诺,比如你想輸入漢字君不見黃河之水天上來 那么對應的拼音則是junbujianhuanghezhishuitianshanglai這么一來,比如你想限制的輸入個數(shù)為10 那么只能輸入到junbujianh這個位置音同。
    那么我們該怎么解決問題呢词爬,進入API我們可以發(fā)現(xiàn)。
    UITextField : UIControl ---- UITextField繼承自UIControl
    有如下函數(shù)
- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;

typedef NS_OPTIONS(NSUInteger, UIControlEvents) {
    UIControlEventTouchDown                                         = 1 <<  0,      // on all touch downs
    UIControlEventTouchDownRepeat                                   = 1 <<  1,      // on multiple touchdowns (tap count > 1)
    UIControlEventTouchDragInside                                   = 1 <<  2,
    UIControlEventTouchDragOutside                                  = 1 <<  3,
    UIControlEventTouchDragEnter                                    = 1 <<  4,
    UIControlEventTouchDragExit                                     = 1 <<  5,
    UIControlEventTouchUpInside                                     = 1 <<  6,
    UIControlEventTouchUpOutside                                    = 1 <<  7,
    UIControlEventTouchCancel                                       = 1 <<  8,

    UIControlEventValueChanged                                      = 1 << 12,     // sliders, etc.
    UIControlEventPrimaryActionTriggered NS_ENUM_AVAILABLE_IOS(9_0) = 1 << 13,     // semantic action: for buttons, etc.

    UIControlEventEditingDidBegin                                   = 1 << 16,     // UITextField
    UIControlEventEditingChanged                                    = 1 << 17,
    UIControlEventEditingDidEnd                                     = 1 << 18,
    UIControlEventEditingDidEndOnExit                               = 1 << 19,     // 'return key' ending editing

    UIControlEventAllTouchEvents                                    = 0x00000FFF,  // for touch events
    UIControlEventAllEditingEvents                                  = 0x000F0000,  // for UITextField
    UIControlEventApplicationReserved                               = 0x0F000000,  // range available for application use
    UIControlEventSystemReserved                                    = 0xF0000000,  // range reserved for internal framework use
    UIControlEventAllEvents                                         = 0xFFFFFFFF
};

我們可以利用此函數(shù)和對應的枚舉UIControlEventEditingChanged來監(jiān)測輸入的內(nèi)容變化权均,從而控制輸入的字數(shù)

代碼如下

- (void)textFiledDidChange:(UITextField *)textField
{
    if (kMaxNumber == 0) return;
    
    NSString *toBeString = textField.text;
    
    NSLog(@" 打印信息toBeString:%@",toBeString);
    
    NSString *lang = [[textField textInputMode] primaryLanguage]; // 鍵盤輸入模式
    if ([lang isEqualToString:@"zh-Hans"]) { // 簡體中文輸入顿膨,包括簡體拼音,健體五筆叽赊,簡體手寫
        
        //判斷markedTextRange是不是為Nil恋沃,如果為Nil的話就說明你現(xiàn)在沒有未選中的字符,
        //可以計算文字長度必指。否則此時計算出來的字符長度可能不正確
        
        UITextRange *selectedRange = [textField markedTextRange];
        //獲取高亮部分(感覺輸入中文的時候才有)
        UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
        // 沒有高亮選擇的字囊咏,則對已輸入的文字進行字數(shù)統(tǒng)計和限制
        if (!position)
        {
            //中文和字符一起檢測  中文是兩個字符
            if ([toBeString getStringLenthOfBytes] > kMaxNumber)
            {
                textField.text = [toBeString subBytesOfstringToIndex:kMaxNumber];
                
            }
        }
    }
    else
    {
        if ([toBeString getStringLenthOfBytes] > kMaxNumber)
        {
            textField.text = [toBeString subBytesOfstringToIndex:kMaxNumber];
        }
    }
}

其中有正則表達式的驗證,方法我是寫在NSString的擴展中的塔橡,具體如下


//.h文件
#import <Foundation/Foundation.h>

@interface NSString (category)

- (NSInteger)getStringLenthOfBytes;

- (NSString *)subBytesOfstringToIndex:(NSInteger)index;

@end


//.m文件

#import "NSString+category.h"

@implementation NSString (category)

- (NSInteger)getStringLenthOfBytes
{
    NSInteger length = 0;
    for (int i = 0; i<[self length]; i++) {
        //截取字符串中的每一個字符
        NSString *s = [self substringWithRange:NSMakeRange(i, 1)];
        if ([self validateChineseChar:s]) {
            
            NSLog(@" s 打印信息:%@",s);
            
            length +=2;
        }else{
            length +=1;
        }
        
        NSLog(@" 打印信息:%@  %ld",s,(long)length);
    }
    return length;
}

- (NSString *)subBytesOfstringToIndex:(NSInteger)index
{
    NSInteger length = 0;
    
    NSInteger chineseNum = 0;
    NSInteger zifuNum = 0;
    
    for (int i = 0; i<[self length]; i++) {
        //截取字符串中的每一個字符
        NSString *s = [self substringWithRange:NSMakeRange(i, 1)];
        if ([self validateChineseChar:s])
        {
            if (length + 2 > index)
            {
                return [self substringToIndex:chineseNum + zifuNum];
            }
            
            length +=2;
            
            chineseNum +=1;
        }
        else
        {
            if (length +1 >index)
            {
                return [self substringToIndex:chineseNum + zifuNum];
            }
            length+=1;
            
            zifuNum +=1;
        }
    }
    return [self substringToIndex:index];
}

//檢測中文或者中文符號
- (BOOL)validateChineseChar:(NSString *)string
{
    NSString *nameRegEx = @"[\\u0391-\\uFFE5]";
    if (![string isMatchesRegularExp:nameRegEx]) {
        return NO;
    }
    return YES;
}

//檢測中文
- (BOOL)validateChinese:(NSString*)string
{
    NSString *nameRegEx = @"[\u4e00-\u9fa5]";
    if (![string isMatchesRegularExp:nameRegEx]) {
        return NO;
    }
    return YES;
}

- (BOOL)isMatchesRegularExp:(NSString *)regex {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    return [predicate evaluateWithObject:self];
}


@end

當然梅割,如果遇到UITextView限制字數(shù)的時候,由于不是繼承1所以沒有addtarget方法葛家,但是可以通過添加通知UITextViewTextDidChangeNotification的方法來監(jiān)測 户辞,方法還是和上面一樣。

  • 總結 針對上面兩種不同的方案癞谒,在不同的時候可以選擇不同的方案底燎。希望對大家有幫助,有什么不對的地方弹砚,還望不吝賜教双仍。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市迅栅,隨后出現(xiàn)的幾起案子殊校,更是在濱河造成了極大的恐慌,老刑警劉巖读存,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件为流,死亡現(xiàn)場離奇詭異,居然都是意外死亡让簿,警方通過查閱死者的電腦和手機敬察,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尔当,“玉大人莲祸,你說我怎么就攤上這事⊥钟” “怎么了锐帜?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長畜号。 經(jīng)常有香客問我缴阎,道長,這世上最難降的妖魔是什么简软? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任蛮拔,我火速辦了婚禮,結果婚禮上痹升,老公的妹妹穿的比我還像新娘建炫。我一直安慰自己,他們只是感情好疼蛾,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布肛跌。 她就那樣靜靜地躺著,像睡著了一般察郁。 火紅的嫁衣襯著肌膚如雪衍慎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天绳锅,我揣著相機與錄音西饵,去河邊找鬼。 笑死鳞芙,一個胖子當著我的面吹牛眷柔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播原朝,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼驯嘱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了喳坠?” 一聲冷哼從身側響起鞠评,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎壕鹉,沒想到半個月后剃幌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體聋涨,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年负乡,在試婚紗的時候發(fā)現(xiàn)自己被綠了牍白。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡抖棘,死狀恐怖茂腥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情切省,我是刑警寧澤最岗,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站朝捆,受9級特大地震影響般渡,放射性物質發(fā)生泄漏。R本人自食惡果不足惜右蹦,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一诊杆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧何陆,春花似錦晨汹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至巩剖,卻和暖如春铝穷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背佳魔。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工曙聂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鞠鲜。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓宁脊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贤姆。 傳聞我的和親對象是個殘疾皇子榆苞,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

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