UITextField ,UITextView 输入长度的限制

UITextField


方法一:UITextFieldDelegate(Tip:中文联想输入状态有问题)

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;   // return NO to not change text
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (textField == self.titleField) {
        if (string.length == 0) return YES;

        NSInteger existedLength = textField.text.length;
        NSInteger selectedLength = range.length;
        NSInteger replaceLength = string.length;
        if (existedLength - selectedLength + replaceLength > 30) {
            return NO;
        }
    }

    return YES;
}

但是当你输入29个字符后,第30个字符以中文汉字的形式继续输入,那么系统会在键盘上方提供后续的一系列联想词,你会发现通过这种方式可以连续选字输入从而突破30个字符的限制。

方法二:UITextFieldTextDidChangeNotification

UIKIT_EXTERN NSString *const UITextFieldTextDidChangeNotification;
[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
- (void)textFieldDidChange:(UITextField *)textField
{
    if (textField == self.titleField) {
        if (textField.text.length > 20) {
            textField.text = [textField.text substringToIndex:20];
        }
    }
}

这样就能实现限制UITextField字数的要求。

UITextView


方法一:UITextViewTextDidChangeNotification

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewDidChange:) name:UITextViewTextDidChangeNotification object:nil];
//假如限制输入30个字符
- (void)textViewDidChange:(NSNotification *)notification
{
    self.placeholder.hidden = (self.textView.text.length > 0);

    if (self.textLengthLimit > 0 && self.textView.text.length > self.textLengthLimit) {
        self.textView.text = [self.text substringToIndex:self.textLengthLimit];
    }
}

这样处理后,我敲着键盘输入了若干个字符,当到达30个字符时就不会再输入了。但是当我从网页上复制一大堆中文内容(远超过30字),粘贴到UITextView中,之后再尝试输入,则会挂掉:
(ps:实际测试发现在iOS7.+版本会crash;但是iOS8.+却不会。。。)

-[NSConcreteTextStorage attributesAtIndex:effectiveRange:]: Range or index out of bounds  

这时需要配合UITextViewDelegate方法:

方法二:UITextViewDelegate

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    if (textView.text.length >= self.textLengthLimit && text.length > range.length) {
        return NO;
    }

    return YES;
} 

- (void)textViewDidChange:(UITextView *)textView
{
    self.placeholder.hidden = (self.textView.text.length > 0);

    if (textView.markedTextRange == nil && self.textLengthLimit > 0 && self.text.length > self.textLengthLimit) {
        textView.text = [textView.text substringToIndex:self.textLengthLimit];
    }
}

这样在输入达到30以后,就不再响应输入变化了,解决了输入达到限制后再输入crash问题;
但是还有另外一个问题:粘贴完达到超过限制个字符后,可以退格删除,再使用中文输入法进行输入,这时候进入multistage text input模式参考这里,会出现这样的问题:

Terminating app due to uncaught exception 'NSRangeException', reason: 'NSMutableRLEArray replaceObjectsInRange:withObject:length:: Out of bounds'  

由于中文输入法的键盘上有联想、推荐的功能,所以可能导致文本内容长度上有些不符合预期,导致越界,所以可以参考这份回答做下处理:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    if (textView.text.length >= self.textLengthLimit && text.length > range.length) {
        return NO;
    }

    return YES;
}

- (void)textViewDidChange:(UITextView *)textView
{
    self.placeholder.hidden = (self.textView.text.length > 0);

    if (textView.markedTextRange == nil && self.textLengthLimit > 0 && self.text.length > self.textLengthLimit) {
        textView.text = [textView.text substringToIndex:self.textLengthLimit];
    }
}

这样就完美的实现了UITextView输入字数限制的效果。

ps:感谢jasonLee的博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值