實(shí)際開(kāi)發(fā)中經(jīng)常遇到文本字?jǐn)?shù)限制的需求,比如發(fā)布朋友圈時(shí)輸入正文長(zhǎng)度不能超過(guò)1000字,輸入用戶名時(shí)限制長(zhǎng)度不能超過(guò)10個(gè)字符。有時(shí)要求中文和表情都按照一個(gè)字符計(jì)數(shù),有時(shí)要求按照兩個(gè)字符計(jì)數(shù)。甚至,有時(shí)還要限制用戶名中不能包含除數(shù)字、字母、中外外的其他字符。
不同字符的長(zhǎng)度
- 英文字符:字符串長(zhǎng)度為1,字節(jié)長(zhǎng)度為1
- 中文字符:字符串長(zhǎng)度為1,字節(jié)長(zhǎng)度為2
- emoji符號(hào):字符串長(zhǎng)度可能為2、5、7、11等等,字節(jié)長(zhǎng)度可能為4、12、18等(emoji可以通過(guò)添加控制符進(jìn)行變體、通過(guò)添加鏈接符進(jìn)行連接等)
- 其他字符:不同語(yǔ)言的字符各不相同
文本輸入控件
- UITextField:通過(guò)監(jiān)聽(tīng)通知UITextFieldTextDidChangeNotification實(shí)現(xiàn)在控件文本內(nèi)容發(fā)生變化時(shí)進(jìn)行字?jǐn)?shù)限制判斷。再使用代理方法-textField:shouldChangeCharactersInRange:replacementString:配合實(shí)現(xiàn)輸入控制。
- UITextView:通過(guò)代理方法-textViewDidChange:和-textView:shouldChangeTextInRange:replacementText:
通常需要在控件文本內(nèi)容發(fā)生變化時(shí),進(jìn)行字?jǐn)?shù)限制判斷。
統(tǒng)計(jì)字符串的字符個(gè)數(shù)
NSInteger len = text.length;
統(tǒng)計(jì)字符串的字節(jié)長(zhǎng)度
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSData *data = [text dataUsingEncoding:enc];
NSInteger dataLen = data.length;
遍歷字符串
[text enumerateSubstringsInRange:NSMakeRange(0, text.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
//
}];
UITextView實(shí)例
#pragma mark - UITextViewDelegate
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if (text.length == 0) { return YES; }
return textView.text.length < 30;
}
- (void)textViewDidChange:(UITextView *)textView
{
NSString *text = textView.text;
NSInteger c = 30;
if (text.length > c)
{
if (textView.markedTextRange) { return; }
textView.text = [text substringToIndex:c];
}
}
UITextField實(shí)例
#pragma mark - UITextField Change Text
- (void)textFieldTextDidChange:(NSNotification *)notification
{
UITextField *textField = notification.object;
NSString *text = textField.text;
NSInteger c = 8;
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSData *data = [text dataUsingEncoding:enc];
if (data.length > c)
{
if (textField.markedTextRange) { return; }
NSMutableString *newText = [NSMutableString string];
__block NSInteger count = 0;
[text enumerateSubstringsInRange:NSMakeRange(0, text.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
NSData *da = [substring dataUsingEncoding:enc];
if (da.length <= c - count)
{
[newText appendString:substring];
count += da.length;
}
else
{
*stop = YES;
}
}];
textField.text = newText;
}
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSLog(@"string:%@, range:%@", string, [NSValue valueWithRange:range]);
if (string.length == 0) { return YES; }
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSData *data = [textField.text dataUsingEncoding:enc];
return data.length < 8;
}