如何限制UITextView上文字的长度

这个问题基本有两种解决思路,一是在输入完毕或即将返回时判断文字的长度是否超过限制,  这种方法实现起来简单,只需在委托方法

-(BOOL)textViewShouldEndEditing:(UITextView *)textView  中加以判断即可,但是这种方式体验不好。

  另外一种就是通过  

-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text  及

-(void)textViewDidChange:(UITextView *)textView  

两个委托方法来在输入过程中进行空间,这种方法实现起来比较复杂,特别是对于中文拼音输入时字符跟字符间夹杂着空格的情况,处理起来比较头疼,稍不注意就会引起crash。


下面讲述第二种思路的实现:

1. 首先,添加一个键盘监听的类KeyboardHandler,监听键盘出现和隐藏以及高度改变的事件,并且向UItextview所在的viewcontroller发出通知,或采用kvo的方式监听键盘高

度。

// Call this method sometwhere in your view controller setup code.

- (void)registerForKeyboardNotifications

{

    [[NSNotificationCenter defaultCenter] addObserver:self

                                             selector:@selector(keyboardChange:)

                                                 name:UIKeyboardWillShowNotification

                                               object:nil];

    

    [[NSNotificationCenter defaultCenter] addObserver:self

                                             selector:@selector(keyboardChange:)

                                                 name:UIKeyboardWillHideNotification

                                               object:nil];

}


- (void)removeForKeyboardNotifications

{

    

    [[NSNotificationCenter defaultCenter] removeObserver:self

                                                    name:UIKeyboardWillShowNotification

                                                  object:nil];

    

    [[NSNotificationCenter defaultCenter] removeObserver:self

                                                    name:UIKeyboardWillHideNotification

                                                  object:nil];

}


- (void)keyboardChange:(NSNotification *)aNotification

{

    NSDictionary *info = (NSDictionary*)[aNotification userInfo];

    NSValue *valueBegin = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];

    NSValue *valueEnd = [info objectForKey:UIKeyboardFrameEndUserInfoKey];


    // Get the size of the keyboard

    CGSize keyboardSizeBegin = [valueBegin CGRectValue].size;

    CGSize keyboardSizeEnd = [valueEnd CGRectValue].size;

    

    if ([aNotification.name isEqualToString:UIKeyboardWillShowNotification]) {

        if (_show) {                     // 更改输入法

            if (keyboardSizeEnd.height != keyboardSizeBegin.height) {

                _offset = keyboardSizeBegin.height - keyboardSizeEnd.height;

                _accessor.frame = [self updateAccessorFrame:_accessor.frame];

                self.keyboardHeight = keyboardSizeEnd.height;

            }

            return;

        }

        

        _offset = self.accessorOffset == 0 ? -keyboardSizeBegin.height : -self.accessorOffset;

        [self updateAccessorAnimate:_animating];

        self.keyboardHeight = keyboardSizeEnd.height;

        _show = YES;

        

    } else if ([aNotification.name isEqualToString:UIKeyboardWillHideNotification])

    {

        if (!_show) {

            return;

        }

        _offset = self.accessorOffset == 0 ? keyboardSizeEnd.height : self.accessorOffset ;

        [self updateAccessorAnimate:_animating];

        self.keyboardHeight = keyboardSizeEnd.height;

        _show = NO;

    }else

    {

        

    }

}


2. 在UItextview所在的viewcontroller 增加两个属性

@property(nonatomic,assign) BOOL   isTypingChineseCharacter;  //是否正在输入中文

@property(nonatomic,strong) NSString*  textAfterChange;  //上一次改变时文本框内的文字


初始化keyboardHandler 并监听键盘高度的变化,主要是为了对中文输入进行处理

  self.keyboardHandler = [QLKeyboardHandler keyboardNotification];

    [self.keyboardHandler registerForKeyboardNotifications];

    [self.keyboardHandler addObserver:self forKeyPath:QLKEYNAME_KEYBOARD_HEIGHT options:NSKeyValueObservingOptionNew context:nil];


-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

{

    if ([keyPath isEqualToString:QLKEYNAME_KEYBOARD_HEIGHT]) {

        CGFloat  newHeight = [[change objectForKey:@"new"]floatValue];

      //  NSLog(@"newHeight:%f",newHeight);

        if (newHeight == kEnglishKeyboardHeight) {

            self.isTypingChineseCharacter = NO;

        }else if (newHeight == kChineseKeyboardHeight){

            self.isTypingChineseCharacter = YES;

        }

    }

}



3. 实现UITextView的委托方法

//在输入字符后,即将改变textView

-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text

{

    BOOL shouldChange =YES;

    //对于换行符,直接处理为退出

    if ([text isEqualToString:@"\n"]) {

        //完成编辑

        [textView resignFirstResponder];

        return NO;

    }


    //英文输入过程中,如果文字超出长度限制,后面的直接不让输,但对于中文必须让用户继续输完拼音,选词的时候再截断

    NSInteger  charactersAfterChange = textView.text.length + text.length - range.length;

    if (!_isTypingChineseCharacter && charactersAfterChange > maxTextLength) {

        shouldChange = NO;

    }

    return shouldChange;

}


//在输入了字符(不限中英文)或者选定了中文词语后

-(void)textViewDidChange:(UITextView *)textView

{

    NSInteger textCount = textView.text.length;

    //如果是中文拼音输入的话,在输入完毕后的选词阶段会调用两次textViewDidChange 利用这个特性可以记录上一次调用时文本框内的字符,如果跟这一次的字符一样,则说明是中文选词。

    BOOL  didSelectWord = NO;

    if ([textView.text isEqualToString:self.textAfterChange]) {

        didSelectWord = YES;

    }

    //如果是英文输入下,直接截断超出长度限制的文字

    if (textCount>maxTextLength && !_isTypingChineseCharacter) {

        textView.text = [textView.text substringToIndex:maxTextLength];

    }

    //如果是中文输入,情况要复杂一点,不能在选词阶段直接截断文字,否则会crash,必须等词选好,即将出现在文本框内的时候再阶段(也就是第二次调用textViewDidChange的时候)

    else if (textCount>maxTextLength && _isTypingChineseCharacter && didSelectWord){

        textView.text = [textView.text substringToIndex:maxTextLength];

    }

   _textAfterChange = textView.text;

   NSLog(@"textCount = %d",_textAfterChange.length);

    _textCountLabel.text = [NSString stringWithFormat:@"%d",maxTextLength- _textAfterChange.length];

}

这里有个问题,就是当连续输入中文的拼音首字母时,比如输入ttss 之类的文字, 文字的长度并不是输入一个字符就增加一个长度,而是1个字符可能对应1个或2个长度。 在textViewDidChange中打印textView.text,可以看到,text的长度是先增加后减少的,这主要是因为苹果为了区分 不同中文字 而在字符之间加了空格。但是这样就给程序造成了麻烦, 没办法通过textView的文字长度来判断是否该截断。 因为如果在拼音没有输完的情况下截断正在输入的文字会造成程序 crash。经过反复探索实践,我发现在中文输入拼音的时候,如果点了拼音对应的词语,textView会向他的委托调用两次textViewDidChange, 并把词语写到 textView后面,如果发现 两次调用的文字内容不一样,就会抛出异常 。 那么,找到问题之后,就可以对症下药了,只要 增加一个变量,记录上一次文字改变时的内容, 确保在 第二次截断文字,第一次不截断, 就不会报错了。


  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值