美文网首页首页投稿(暂停使用,暂停投稿)iOS 开发 iOS Developer
IOS7上一种计算属性文本高度导致的Crash分析

IOS7上一种计算属性文本高度导致的Crash分析

作者: 狂风无迹 | 来源:发表于2016-07-12 23:01 被阅读277次

    <p>  比较长的一段时间以来,一直有一个IOS7下的crash不时的出现,近期终于找到一个crash现场,实在是个令人兴奋的消息。</p>
    <p>二话不说,先上堆栈:</p>

    crash堆栈

    <p>从堆栈上可以看出,crash发生在系统的API里面。而且仅仅是IOS8以下的系统才会发生,说明在IOS8以上的系统,苹果已经意识到了这个问题,将其修复了。
    </p>
    <p>
    那么导致问题的原因究竟是什么?
    </p>
    <p>@"-信 仰。اللهأكبر:";
    </p>
    <p>如上所示,就是这个莫名其妙的字符串,导致的属性文本在计算高度的时候直接crash。利用万能的谷歌一查,这句是个阿拉伯语,大意是“真主伟大”。为何阿拉伯语会导致IOS的系统API产生crash?
    </p>
    <p>引用知乎上大牛们的解释:“这个 bug 应该归结为苹果从 WebCore 到 CoreText 都存在设计缺陷,对从右往左的编辑方向支持的不好,设计上没有考虑这种字符序列,而不能单纯说 WebCore 或者 CoreText 的某个地方有个小 bug。"
    </p>
    <p>上面这个问题算是见过的最为接近的问题了,而且crash的堆栈也及其类似。所不同的是,上面的问题发生IOS6上面(这种老古董的系统大家就别用了吧!),据说在IOS7上面已经得到修复。不过现实是目前在处理属性文本中含有阿拉伯文时,IOS系统的表现就是不稳定。

    既然是这样,那一种处理方法就是将文本中的阿拉伯文过滤掉了,替换成空格或者其它什么的。以便使用不包含阿拉伯文的文本来计算size。

    需要如何替换?
    这里就要用到unicode编码的相关知识了。阿拉伯文一般使用unicode编码,我们找到它们的具体位置(unicode字符编码表):

    unicode编码位置

    阿拉伯文的范围为0x600到0x6FF。这样通过IOS的NSMutableCharacterSet对象,我们就可以找到需要过滤的字符集合。

    简单的算法如下:
    <code>
    + (NSCharacterSet *)tExceptSet
    {

    // 异常字符集合

    static NSCharacterSet *exceptSet;
    if (exceptSet == nil)
    {
        NSMutableCharacterSet *aCharacterSet = [[NSMutableCharacterSet alloc] init];
        
        NSRange lcEnglishRange;
        lcEnglishRange.location = (unsigned int)0x0600;
        lcEnglishRange.length = (unsigned int)0x06ff - (unsigned int)0x0600;
        [aCharacterSet addCharactersInRange:lcEnglishRange];
        exceptSet = aCharacterSet;
    }
    return exceptSet;
    

    }

    - (NSString )ttLegalNickName:(NSString)nickName
    {

    NSString* legalNickName = nickName;
    if(!IS_IOS_UPPER(@"8.0")) {
        NSCharacterSet *illegalCharacterSet = [CommentInfo tExceptSet];
        
        legalNickName = [[nickName componentsSeparatedByCharactersInSet:illegalCharacterSet] componentsJoinedByString:@""];
    }
    return legalNickName;
    

    }
    </code>
    </p>
    <p>
      在应用上述过滤方法之后,部分IOS8以下的系统会受到小小的影响,但是相比较直接闪退而言,这样还算是比较令人接受的了。当然过滤只是一种方式,另外换一个场景,直接用上面的阿拉伯字符串算属性文本的高度,当文本很简单的时候并未发生Crash。或许这个问题还有更好的解决方案,各位如果知道,不妨告诉我。。
    </p>

    相关文章

      网友评论

        本文标题:IOS7上一种计算属性文本高度导致的Crash分析

        本文链接:https://www.haomeiwen.com/subject/nirsjttx.html