关于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;
}
到此,大功告成!!!