iOS中對(duì)文本的字符限制示例詳解
需求
1.對(duì)于文本框,字?jǐn)?shù)限制是一種很常見的需求,判斷text.length 即可,然而交互提出了對(duì)字符限制,一個(gè)英文、一個(gè)數(shù)字 對(duì)應(yīng)一個(gè)字符,一個(gè)漢字 對(duì)應(yīng) 兩個(gè)字符,并只可以輸入中英文數(shù)字。so what,要腫么辦呢?
知識(shí)儲(chǔ)備
- TextField
- lengthOfBytesUsingEncoding 方法
- characterAtIndex
首先,對(duì)于正常字?jǐn)?shù)限制的一些操作此處就不講解了。
方法如下
我們需要監(jiān)聽textfield
[textfield addTarget:self action:@selector(textFieldTextEditingChanged:) forControlEvents:UIControlEventEditingChanged];
那么,我們?yōu)槭裁床挥?textfield代理方法
-(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
對(duì)于字符計(jì)算來說,使用中文聯(lián)想詞容易產(chǎn)生誤差,并且有些情況并不會(huì)走上述協(xié)議方法,此處沒有深究。
- (void)textFieldTextEditingChanged:(UITextField *)field
{
//不支持系統(tǒng)表情的輸入
if ([[textField textInputMode] primaryLanguage]==nil||[[[textField textInputMode] primaryLanguage]isEqualToString:@"emoji"]) {
return;
}
//中英文數(shù)字判斷
NSString *strig =[[NSString alloc]initWithString:textField.text];
[strig enumerateSubstringsInRange:NSMakeRange(0, strig.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
if (substring.length >=2) {
textField.text =[textField.text stringByReplacingOccurrencesOfString:substring withString:@""];
}
}];
NSString *toBeString = textField.text;
NSString *lastString;
if(toBeString.length>0){
lastString=[toBeString substringFromIndex:toBeString.length-1];
if ([self isInputRuleAndNumber:lastString] != YES) {
textField.text = [toBeString substringToIndex:toBeString.length-1];
}
}
if (textField.text.length == 0) {
return;
}
NSString *lang = [textField.textInputMode primaryLanguage]; // 鍵盤輸入模式
if ([lang isEqualToString:@"zh-Hans"]) { // 簡體中文輸入,包括簡體拼音,健體五筆,簡體手寫
UITextRange *selectedRange = [textField markedTextRange];
//獲取高亮部分
UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
// 沒有高亮選擇的字,則對(duì)已輸入的文字進(jìn)行字?jǐn)?shù)統(tǒng)計(jì)和限制
if (!position) {
if ([self unicodeLengthOfString:textField.text] > kMaxLength){
[self saveOKText:textField.text];
return;
}
}
// 有高亮選擇的字符串,則暫不對(duì)文字進(jìn)行統(tǒng)計(jì)和限制
else{
}
}else{ // 中文輸入法以外的直接對(duì)其統(tǒng)計(jì)限制即可,不考慮其他語種情況
if ([self unicodeLengthOfString:textField.text] > kMaxLength) {
[self saveOKText:textField.text];
return;
}
}
}
上述方法 ,調(diào)用了三個(gè)重要方法
isInputRuleAndNumber 此方法對(duì)于 手寫時(shí)出現(xiàn)的一些圖案沒有剔除
#pragma mark - 謂詞條件限制
/**
pattern中,輸入需要驗(yàn)證的通過的字符
小寫a-z
大寫A-Z
漢字\u4E00-\u9FA5
數(shù)字\u0030-\u0039
@param str 要過濾的字符
@return YES 只允許輸入字母和漢字
*/
- (BOOL)isInputRuleAndNumber:(NSString *)str {
NSString *pattern = @"[a-zA-Z\u4E00-\u9FA5\\u0030-\\u0039]";
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", pattern];
BOOL isMatch = [pred evaluateWithObject:str];
return isMatch;
}
字符計(jì)算 unicodeLengthOfString
參考iOS textField限制字符串長度 字符數(shù)
-(NSUInteger)unicodeLengthOfString:(NSString *) text {
NSUInteger asciiLength = 0;
for (NSUInteger i = 0; i < text.length; i++) {
unichar uc = [text characterAtIndex: i];
asciiLength += isascii(uc) ? 1 : 2;
}
return asciiLength;
}
當(dāng)時(shí)想,當(dāng) 字符數(shù)大于 最大字符數(shù) 就把 當(dāng)前textField.text.length 減一取值,但是對(duì)于粘貼復(fù)制 超過 字符數(shù)不止一個(gè)長度時(shí),就出現(xiàn)問題了。那么我們?nèi)绾谓鉀Q呢?
此處,我想到了使用遞歸,先判斷,最后一個(gè)str,利用unicodeLengthOfString 我們就可以知道 最后str 的字符長度,不論是 字母、數(shù)字還是漢字,對(duì)于超出的字符數(shù),進(jìn)行判斷,刪除多余長度。
- (void )saveOKText:(NSString *)textStr
{
int overLength = (int)[self unicodeLengthOfString:textStr] - kMaxLength;//超出的字符數(shù)
if (overLength <= 0 ){
_field.text = textStr;
return;
}
NSString *lastStr = [textStr substringFromIndex:textStr.length-1];
if ([self unicodeLengthOfString:lastStr] >= 2) {
textStr = [textStr substringToIndex:textStr.length-1];
NSLog(@"%@",textStr);
if (overLength >0) {
NSLog(@"%@",textStr);
[self saveOKText:textStr];
}else{
_field.text = textStr;
return;
}
}else if ([self unicodeLengthOfString:lastStr] == 1) {
textStr = [textStr substringToIndex:textStr.length-1];
if (overLength >0) {
[self saveOKText:textStr];
}else{
_field.text = textStr;
return;
}
}
}
其實(shí),對(duì)于此處判斷來說,不用再去判斷字母、數(shù)字還是漢字,對(duì)于超出的字符數(shù),遞歸刪除就好。
此方法 只適用于 中英文的輸入,如果還需要輸入表情,此方法就不適用了。
還有前面提到的 知識(shí)儲(chǔ)備中的方法:
- (NSUInteger)lengthOfBytesUsingEncoding:(NSStringEncoding)enc
按照編碼返回字節(jié)數(shù)
Unicode:
0x00-0x7F的字符,用單個(gè)字節(jié)來表示;
0x80-0x7FF的字符用兩個(gè)字節(jié)表示;
0x800-0xFFFF的字符用3字節(jié)表示;
漢字的unicode范圍是:0x4E00~0x9FA5
一個(gè)漢字 三個(gè)字符,不符合需求。
- (unichar)characterAtIndex:(NSUInteger)index
返回字符
isascii是C語言中的字符檢測函數(shù)。通常用于檢查參數(shù)c是否為ASCII 碼字符,也就是判斷c 的范圍是否在0 到127 之間。
unichar uc = [text characterAtIndex: i]; asciiLength += isascii(uc) ? 1 : 2;
數(shù)字、字母 的ascii碼值 都在 0-127 之間,字符為1,其他為2。
textView 使用的時(shí)候類似。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
iOS中利用CAEmitterLayer實(shí)現(xiàn)粒子動(dòng)畫詳解
粒子效果應(yīng)該對(duì)現(xiàn)在很多人來說并不陌生,我們之前也分享了一些相關(guān)文章,下面這篇文章主要給大家介紹了關(guān)于iOS中利用CAEmitterLayer實(shí)現(xiàn)粒子動(dòng)畫的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友們下面來一起看看吧。2017-06-06
OC - 9.基于Quartz2D繪制下載進(jìn)度條(demo)
這篇文章主要介紹了OC - 9.基于Quartz2D繪制下載進(jìn)度條(demo)的相關(guān)資料,需要的朋友可以參考下2015-11-11
iOS中的AutoLayout使用實(shí)踐總結(jié)
在對(duì)界面進(jìn)行布局的時(shí)候,我們經(jīng)常使用AutoLayout對(duì)界面進(jìn)行布局適配。下面這篇文章主要給大家介紹了iOS中AutoLayout使用實(shí)踐的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2017-12-12
iOS中滑動(dòng)控制屏幕亮度和系統(tǒng)音量(附加AVAudioPlayer基本用法和Masonry簡單使用)
這篇文章主要介紹了iOS中滑動(dòng)控制屏幕亮度和系統(tǒng)音量(附加AVAudioPlayer基本用法和Masonry簡單使用)的相關(guān)資料,需要的朋友可以參考下2016-12-12
IOS中用正則表達(dá)式判斷輸入的內(nèi)容為8-16位且同時(shí)包含數(shù)字和字母
這篇文章主要介紹了IOS中用正則表達(dá)式判斷輸入的內(nèi)容為8-16位且同時(shí)包含數(shù)字和字母,需要的朋友可以參考下2017-06-06
IOS 實(shí)現(xiàn)微信自動(dòng)搶紅包(非越獄IPhone)
這篇文章主要介紹了IOS 實(shí)現(xiàn)微信自動(dòng)搶紅包(非越獄IPhone)的相關(guān)資料,這里對(duì)實(shí)現(xiàn)自動(dòng)搶紅包做一個(gè)詳細(xì)的實(shí)現(xiàn)步驟,需要的朋友可以參考下2016-11-11
iOS驗(yàn)證手機(jī)號(hào)的正則表達(dá)式
這篇文章主要為大家詳細(xì)介紹了iOS驗(yàn)證手機(jī)號(hào)的正則表達(dá)式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12

