UITextField限制字符(数字英文一个,中文两个)

关于UITextField字数限制,以前都是根据length来计算的,但是现在项目需求按照字符计算,也就是说英文数字占用一个字符,汉字两个字符,表情四个字符.
需求已明确,接下来就是该如何实现:
难点:
1.区分中英文数字以及表情.
2.超过字符限制,截取到最后一个字符,防止出现乱码(关于乱码,有些人可能不太明白,举个例子:限制十个字符,当你输入8个字符时,在输入一个表情,截取前10位,你会发现表情会截取一半,从而出现乱码)
3.高亮部分超出字符限制,允许继续输入
4.字符长度的计算

英文数字检测:

 unichar ch = [string characterAtIndex:substringRange.location];
 if (isascii(ch) == 1) {
      //此处是英文和数字
  } else {
    //其他
}

表情检测:

-(BOOL)stringContainsEmoji:(NSString *)string
{
__block BOOL returnValue = NO;

[string enumerateSubstringsInRange:NSMakeRange(0, [string length])
                           options:NSStringEnumerationByComposedCharacterSequences
                        usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                            const unichar high = [substring characterAtIndex: 0];
                            
                            // Surrogate pair (U+1D000-1F9FF)
                            if (0xD800 <= high && high <= 0xDBFF) {
                                const unichar low = [substring characterAtIndex: 1];
                                const int codepoint = ((high - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
                                
                                if (0x1D000 <= codepoint && codepoint <= 0x1F9FF){
                                    returnValue = YES;
                                }
                                
                                // Not surrogate pair (U+2100-27BF)
                            } else {
                                if (0x2100 <= high && high <= 0x27BF){
                                    returnValue = YES;
                                }
                            }
                        }];

return returnValue;
}

字符长度计算

-(int)getInfoWithText:(NSString *)text maxLength:(NSInteger)maxLength
{
    int length = 0;
    char *p = (char )[text cStringUsingEncoding:NSUnicodeStringEncoding];
    for (int i = 0; i < [text lengthOfBytesUsingEncoding:NSUnicodeStringEncoding]; i++) {
    if (p) {
    length++;
    if (length <= maxLength) {

        }
    }
      else {
          if (length <= maxLength) {

          }
      }
      p++;
}
    return length;
}

有了以上这些基础,我们就可以知道字符长度以及截取长度:
我提供两种方法:
第一种:

struct BPTextInfo {
NSInteger length;//字符长度
NSInteger number;//截取长度
};
typedef struct BPTextInfo BPTextInfo;

-(BPTextInfo)getTextFieldText:(NSString *)string maxLength:(NSInteger)maxLength
{
    BPTextInfo textInfo;
    __block NSInteger length = 0;
    __block NSInteger number = 0;
    [string enumerateSubstringsInRange:NSMakeRange(0, [string length])
                           options:NSStringEnumerationByComposedCharacterSequences
                        usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                            const unichar high = [substring characterAtIndex: 0];
                            
                            // Surrogate pair (U+1D000-1F9FF)
                            if (0xD800 <= high && high <= 0xDBFF) {
                                const unichar low = [substring characterAtIndex: 1];
                                const int codepoint = ((high - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
                                
                                if (0x1D000 <= codepoint && codepoint <= 0x1F9FF)  {
                                   length +=4;
                                    if (length <= maxLength) {
                                    number = number + 2;
                                    }
                                } else {
                                      unichar ch = [string characterAtIndex:substringRange.location];
                                    if (isascii(ch) == 1) {
                                        length ++;
                                    } else {
                                        length = length + 2;
                                    }
                                    if (length <= maxLength) {
                                    number ++;
                                }
}
                                
                                // Not surrogate pair (U+2100-27BF)
                            } else {
                                if (0x2100 <= high && high <= 0x27BF){
                                    length +=4;
                                    if (length <= maxLength) {
                                    number = number + 2;
                                }
                                }
                                    else {
                                      unichar ch = [string characterAtIndex:substringRange.location];
                                    if (isascii(ch) == 1) {
                                        length ++;
                                    } else {
                                        length = length + 2;
                                    }
                                    if (length <= maxLength) {
                                    number ++;
                                }
                              
                            }
                        }];

    textInfo.length = length;
    textInfo.number = number;

    return textInfo;
}

第二种:骚操作,笔者就是用的这种

-(BPTextInfo)getTextFieldText:(NSString *)string maxLength:(NSInteger)maxLength
{
BPTextInfo textInfo;
__block NSInteger length = 0;
__block NSInteger number = 0;

[string enumerateSubstringsInRange:NSMakeRange(0, [string length])
                           options:NSStringEnumerationByComposedCharacterSequences
                        usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                            if (substringRange.length == 1) {
                                unichar ch = [string characterAtIndex:substringRange.location];
                                if (isascii(ch) == 1) {
                                    length ++;
                                } else {
                                    length = length + 2;
                                }
                                if (length <= maxLength) {
                                    number ++;
                                }
                            } else {
                                length = length + 4;
                                if (length <= maxLength) {
                                    number = number + 2;
                                }
                            }
                        }];
textInfo.length = length;
textInfo.number = number;

return textInfo;
}

第一步:创建UITextField对象;
第二步:为textField添加事件

[self.textField addTarget:self action:@selector(textFieldEditingChanged:) forControlEvents:UIControlEventEditingChanged];

第三部:实现事件方法

-(void)textFieldEditingChanged:(UITextField *)textField
{
NSInteger maxLength = 10;
BPTextInfo text = [self getTextFieldText:textField.text maxLength:maxLength];
//获取高亮部分
UITextRange *selectedRange = [textField markedTextRange];
UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
if (!position || !selectedRange)
{
if (text.length > maxLength) {
textField.text = [textField.text substringToIndex:text.number];
}
}
}

额外提供一个过滤表情方法:

-(NSString *)disable_emoji:(NSString *)text {
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[^\u0020-\u007E\u00A0-\u00BE\u2E80-\uA4CF\uF900-\uFAFF\uFE30-\uFE4F\uFF00-\uFFEF\u0080-\u009F\u2000-\u201f\r\n]"options:NSRegularExpressionCaseInsensitive error:nil];
NSString *modifiedString = [regex stringByReplacingMatchesInString:text
options:0
range:NSMakeRange(0, [text length])
withTemplate:@""];
return modifiedString;
}

到此,大功告成!!!

你可能感兴趣的:(UITextField限制字符(数字英文一个,中文两个))