UITextView & UITextField 实现中英文混合输入的限制

来源:互联网 发布:天谕女角色捏脸数据 编辑:程序博客网 时间:2024/06/01 07:25

最近项目中有了一个新的需求, 用户输入昵称时可以同时输入中英文, 且有字数限制(一个中文汉字 == 两个字母), 一开始感觉不太难啊, 但实现的过程中却发现不如想象中容易, 这里写一篇博客记录一下:

我们知道在iOS开发中, UITextFieldUITextView是两个使用频率非常高的输入控件, 苹果也提供了很多的代理方法供我们使用, 我们的目标就是写一个通用的方法(或者类)来进行字数检测.

首先检测的前提就是要监听到用户输入的每一个汉字或者字母, 这方面UITextView已经为我们提供了代理方法, 每当textView内容改动, 下面的方法都会被触发(前提是我们已经设置好了代理), 我们可以用它来监听UITextView输入内容的改变, 在这个方法里进行字符串截取.

- (void)textViewDidChange:(UITextView *)textView;

至于UITextField, 我也看到过有人用KVO监听UITextFieldTextDidChangeNotification来实现的, 不过我自己是这么处理的:

UITextField *textField = [[UITextField alloc] init];[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];

因为UITextFieldUIControl的子控件, 所以我们可以用addTarget来监听, 然后在textFieldDidChange:这个方法里进行截取.

在继续之前, 让我们先来了解一下编码的概念:

NSString与Unicode

汉字内码扩展规范

关于GBK、GB2312、UTF8

too long too read …..

简单来说, GBK是一种中文编码格式, 支持所有中文字符, 在GBK格式下一个汉字等于2个字节, 一个字母等于1个字节, 我们可以用这种格式来对输入的字符进行截取判断.

这里还有一个问题, 那就是既然我们要对UITextViewUITextField都要进行判断, 难道我们要分别写两个方法吗? 当然不了, 我们可以用KVC来取值呀~~

贴一下代码:

+ (void)textInputView:(id)inputView numberLimit:(NSInteger)limit{     // 先对传入的inputView进行判断    BOOL isTextField = [inputView isKindOfClass:[UITextField class]];    BOOL isTextView = [inputView isKindOfClass:[UITextView class]];    NSAssert(isTextField || isTextView, @"LPTextInputLimitLog - inputView must be a textField or a textView");    // 利用valueForKey取值    NSString *toBeString = [inputView valueForKey:@"text"];    // 判断联想词    UITextRange *selectedRange = [inputView markedTextRange];    UITextPosition *position = [inputView positionFromPosition:selectedRange.start offset:0];    // 如果不是联想词, 我们再进行处理    if (!position) {         // 用GBK对字符串进行编码, 转换, 获取长度        NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);        NSData *toBeStringData = [toBeString dataUsingEncoding:encoding];        NSInteger dataLength = [toBeStringData length];        // 一旦输入的长度超过了我们的限制, 立刻进行处理.        if (dataLength > limit) {              // 截取limit长度的data, 利用GBK编码回转为string, 这里要注意, 因为我们可能截取出来半个汉字(直接分尸了......)            NSString *limitString = [[NSString alloc] initWithData:[toBeStringData subdataWithRange:NSMakeRange(0, limit)] encoding:encoding];            // 这里做一下判断, 因为如果截出来半个汉字的话,string是不会有值的.            if (!limitString) limitString = [[NSString alloc] initWithData:[toBeStringData subdataWithRange:NSMakeRange(0, limit - 1)] encoding:encoding];            // 最后, 我们把截取出来的字符串用KVC赋值给inputValue的'text'属性, 这就完成了截取的任务.(这里最好有个弹窗提示一下用户)            [inputView setValue:limitString forKey:@"text"];        } else {            [inputView setValue:toBeString forKey:@"text"];        }    }}

说一下截串这里的逻辑: 比如我们限制10个字符, 可能第九个字符是一个字母, 这时我们再输入一个汉字, 截取的limit就包含半个汉字了, 这时我们在往前截取一位, 把字母截取出来而汉字刨除, 这样就没有问题了.

如果我写的代码有问题或者大家有更好的方法, 欢迎留言探讨 :]

0 0
原创粉丝点击