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];
            }
        }
    }

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

时间: 2024-12-28 01:30:28

UITextField限制汉字数量最正确的姿势,解决iOS7下substringToIndex方法导致的崩溃的相关文章

二分查值,正确的姿势

04:网线主管 总时间限制:  1000ms 内存限制:  65536kB 描述 仙境的居民们决定举办一场程序设计区域赛.裁判委员会完全由自愿组成,他们承诺要组织一次史上最公正的比赛.他们决定将选手的电脑用星形拓扑结构连接在一起,即将它们全部连到一个单一的中心服务器.为了组织这个完全公正的比赛,裁判委员会主席提出要将所有选手的电脑等距离地围绕在服务器周围放置. 为购买网线,裁判委员会联系了当地的一个网络解决方案提供商,要求能够提供一定数量的等长网线.裁判委员会希望网线越长越好,这样选手们之间的距

高版本jquery尤其是1.10.2的版本设置input radio设置值的最正确的姿势。

$("input:radio[name="analyshowtype"]").attr("checked",false); $("input[name=jizai]:eq(0)").attr("checked",'checked'); $("input[@type=radio][name=sex][@value=1]").attr("checked",true); 以

NSnotificationCenter 正确使用姿势, removeObject 探索

最近在做平板的过程中,发现了一些很不规范的代码.偶然修复支付bug的时候,看到其他项目代码,使用通知的地方没有移除,我以为我这个模块的支付闪退是因为他通知没有移除的缘故.而在debug和看了具体的代码的时候才发现和这里没有关系.在我印象中,曾经因为没有移除通知而遇到闪退的问题.所以让我很意外,于是写了个demo研究了下,同时来讲下NSNotificationCenter使用的正确姿势. NSNotificationCenter 对于这个没必要多说,就是一个消息通知机制,类似广播.观察者只需要向消

Gradle的依赖方式——Lombok在Gradle中的正确配置姿势

写过java的都知道,lombok几乎在项目中处于不可或缺的一部分,但是lombok在Gradle的项目中配置并非人人都知道. 很多人在项目依赖中直接这样写 1 compile "org.projectlombok:lombok:1.18.4" 但这样的处理在Gradle 5.0以上被命令禁止了,在4.x的高级版本中编译时也会有对应的告警 12345 The following annotation processors were detected on the compile cla

ADODB.Connection 错误 '800a0e7a' 未找到提供程序。该程序可能未正确安装。解决方法!

[问题描述]调试基于ACCESS+ASP的网站程序的时候,遇到如下错误: ADODB.Connection 错误 '800a0e7a' 未找到提供程序.该程序可能未正确安装. /Inc/Function.asp,行 9 [原因分析]因为系统是64位的win7或win8.1所以会出现这个问题,解决方法如下: [解决方法]找到IIS应用程序池,“设置应用程序池默认属性”-->“常规”-->”启用 32 位应用程序”,设置为 True即可解决. ADODB.Connection 错误 '800a0e

虚拟机下centos时间不正确的方便解决方法

就是用NTP了,通过外部的服务同步时间. ntpdate us.pool.ntp.org | logger -t NTP 如果没有ntpdate ,可以使用 yum install ntpdate 进行安装. 当然最好放在crontab里面,各一段时间同步一次就OK. crontab -e * * * * * /usr/sbin/ntpdate us.pool.ntp.org | logger -t NTP 每分钟同步一次,够狠吧. ===============================

Atitit.url 汉字中文路径  404 resin4 resin  解决  v2 q329

Atitit.url 汉字中文路径  404 resin4 resin  解决  v2 q329 1. Pluginx机制1 2. Code1 3. 参考4 1. 原理 过滤器  ,,拦截jpg  with %的url...read img ,直接输出.. 2. Pluginx机制 //if() if(inied==false ||  new File("c:\\chinese_filename_hook_ini_pertime").exists()) { new Pluginx().

mysql like 匹配查询出不正确中文的解决办法

本文讲述mysql使用like语句时,匹配查询出不正确中文的解决办法 mysql like 搜索的时候发现,用 select title from tb_name where title like '%a%' 的时候出来的结果除了包含a的名字外连包含中文“新”的名字也出现在搜索结果里面,这令我想弄清楚mysql的匹配模式和规则到底是怎么样的,另外在匹配的时候正则表达式也很常用! 出现这个问题的原因是:MySQL在查询字符串时是大小写不敏感的,在编绎MySQL时一般以ISO-8859字符集作为默认

<转>jquerymobile动态添加元素之后有些不能被正确渲染的解决方法

jquerymobile动态添加元素之后有些不能被正确渲染的解决方法:listview: 添加 jq(".detail").listview("refresh");div或其他: 添加.trigger( "create" );jq(".detail:eq("+ix+1+")").append("<li>"+data.linete[i].S_Station+data.linet