UITextField最大字符数和最大字节数的限制

UITextView,UITextfield 中有很多坑,网上的方法也很多,但是用过之后暂时没有发现一个好用。这里给大家几组测试用例可以一试,为啥不好用。

  • 限制10个字节,输入2个Emoj之后是8个字节(一个Emoj是4个字节),此时再输入一个中文,看看结果如何(中文的UTF8占3个字节)
  • 限制5个字符,一个Emoj是2个字符,其他都是一个。此时输入两个Emoj,再输入中文,然后中文联想试试。

就目前的情况来说,看了很多资料,并没有一个通用的能限制字符数和字节数的封装。

一. 字符限制

1. 错误方法

常见的这种方法是错误的,会导致Emoj表情的截取问题

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if(range.length + range.location > textField.text.length)
    {
        return NO;
    }
    
    NSUInteger newLength = [textField.text length] + [string length] - range.length;
    return newLength <= 5;
}

这种限制方法会导致拼音下出现这种情况,且无法输入.无法输入满5个字符。在emoj表情也有问题

3.jpeg

2. 推荐方法

使用rangeOfComposedCharacterSequencesForRange, 防止在range范围内整词被截断.因为中文的UTF8是3字节,Emoj是4个字节,且不能边输入边限制,否则中文联想的时候就无法继续输入。只能输入后在textfieldchange的时候进行截断。
综上所述,思路如下:

- (void)textFieldDidChange:(UITextField *)textField
{
    NSString *text = textField.text;
//    NSLog(@"text:%@",text);
    
    UITextRange *selectedRange = [textField markedTextRange];
    UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
    
    // 没有高亮选择的字,则对已输入的文字进行字数统计和限制,防止中文被截断
    
    if (!position){
        //---字符处理
        if (text.length > _maxLength){
            //中文和emoj表情存在问题,需要对此进行处理
            NSRange range;
            NSUInteger inputLength = 0;
            for(int i=0; i < text.length && inputLength <= _maxLength; i += range.length) {
                range = [textField.text rangeOfComposedCharacterSequenceAtIndex:i];
                inputLength += [text substringWithRange:range].length;
                if (inputLength > _maxLength) {
                    NSString* newText = [text substringWithRange:NSMakeRange(0, range.location)];
                    textField.text = newText;
                }
            }
        }
    }
}

二. 字节限制

在UTF8中,英文和数字是1个字节,汉字是3个字节,emoji是3或者4个字节。这里的难度比上面更大,如果截取失败,极有可能出现乱码。这里我们的做法如下

- (void)textFieldDidChange:(UITextField *)textField
{
    NSString *text = textField.text;
//    NSLog(@"text:%@",text);
    
    UITextRange *selectedRange = [textField markedTextRange];
    UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
    
    // 没有高亮选择的字,则对已输入的文字进行字数统计和限制,防止中文被截断
    
    if (!position){
        //---字节处理
        //Limit
        NSUInteger textBytesLength = [textField.text lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
        if (textBytesLength > _maxBytesLength) {
            NSRange range;
            NSUInteger byteLength = 0;
            for(int i=0; i < text.length && byteLength <= _maxBytesLength; i += range.length) {
                range = [textField.text rangeOfComposedCharacterSequenceAtIndex:i];
                byteLength += strlen([[text substringWithRange:range] UTF8String]);
                if (byteLength > _maxBytesLength) {
                    NSString* newText = [text substringWithRange:NSMakeRange(0, range.location)];
                    textField.text = newText;
                }
            }
        }
    }
    if (self.textFieldChange) {
        self.textFieldChange(self,textField.text);
    }
}

你可能感兴趣的:(UITextField最大字符数和最大字节数的限制)