zoukankan      html  css  js  c++  java
  • UITextField限制汉字数量最正确的姿势,解决iOS7下substringToIndex方法导致的崩溃

    今天在写一个限制UITextField汉字数量的需求,原以为非常简单的一个需求,在实际开发中遇到了很多问题.

    首先,汉字的输入时的联想词在输入到TextFiled时,并不会走

    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;

    这导致了在这里进行长度限制的代码都会失效.此路不通.

    经过查找资料,得知可以用注册UITextFieldTextDidChangeNotification通知来监测TextField的文字的变化

    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(textFiledEditChanged:) 
              name:@"UITextFieldTextDidChangeNotification" object:myTextField];
    

      

    在textFiledEditChanged:方法中

    - (void)textDidChanged:(NSNotification *)notification{
        
        NSInteger maxLength = 6;
        UITextField *textField = (UITextField *)notification.object;
    
        if (textField.text.length > maxLength)
        {
            textField.text = [textField.text substringToIndex:maxLength];
        }
    }
    

      这种方法看起来没什么问题,然而实测在iOS7下输入汉字时,一旦长度到达最大长度,再进行输入(此时输入状态还是拼音)就会立即崩溃.

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

    该问题在iOS8以上的系统中不会出现,可能是苹果修复了该BUG.

    再次查找资料,找到这篇博客http://www.jianshu.com/p/2d1c06f2dfa4

    这篇博客解决了UItextFiled在截取字符串时,如果对emoji进行截取会变乱码的问题(原因是emoji实际上占了3个长度).

    UITextField *textField = (UITextField *)obj.object;
        NSString *toBeString = textField.text;
    
        //获取高亮部分
        UITextRange *selectedRange = [textField markedTextRange];
        UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
    
        // 没有高亮选择的字,则对已输入的文字进行字数统计和限制
        if (!position)
        {
            if (toBeString.length > MAX_STARWORDS_LENGTH)
            {
                NSRange rangeIndex = [toBeString rangeOfComposedCharacterSequenceAtIndex:MAX_STARWORDS_LENGTH];
                if (rangeIndex.length == 1)
                {
                    textField.text = [toBeString substringToIndex:MAX_STARWORDS_LENGTH];
                }
                else
                {
                    NSRange rangeRange = [toBeString rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, MAX_STARWORDS_LENGTH)];
                    textField.text = [toBeString substringWithRange:rangeRange];
                }
            }
        }

    测试后发现,这个方法在iOS8以上的系统运行良好,但是在iOS7下居然完全失效了.

    原因是在iOS7下,position对象总是不为nil,导致走不进处理长度的代码.

    研究后发现在需要增加一个判断条件,

    改进后的代码:

    UITextField *textField = (UITextField *)obj.object;
        NSString *toBeString = textField.text;
    
        //获取高亮部分
        UITextRange *selectedRange = [textField markedTextRange];
        UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
    
        // 没有高亮选择的字,则对已输入的文字进行字数统计和限制
        if (!position || !selectedRange)
        {
            if (toBeString.length > MAX_STARWORDS_LENGTH)
            {
                NSRange rangeIndex = [toBeString rangeOfComposedCharacterSequenceAtIndex:MAX_STARWORDS_LENGTH];
                if (rangeIndex.length == 1)
                {
                    textField.text = [toBeString substringToIndex:MAX_STARWORDS_LENGTH];
                }
                else
                {
                    NSRange rangeRange = [toBeString rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, MAX_STARWORDS_LENGTH)];
                    textField.text = [toBeString substringWithRange:rangeRange];
                }
            }
        }
    

    再次测试后没有发现崩溃问题了.

  • 相关阅读:
    A. Maze
    A. Ice Skating (联通块)
    A. DZY Loves Chessboard (找到一个涂一个)
    C. Kefa and Park
    A. Party
    N皇后问题
    八皇后问题
    A. DZY Loves Sequences
    A. Reorder the Array (二分变形)
    BZOJ1681 [Usaco2005 Mar]Checking an Alibi 不在场的证明
  • 原文地址:https://www.cnblogs.com/ashamp/p/5199152.html
Copyright © 2011-2022 走看看