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);
}
}