<p>??比較長的一段時間以來,一直有一個IOS7下的crash不時的出現,近期終于找到一個crash現場,實在是個令人興奮的消息。</p>
<p>二話不說,先上堆棧:</p>
<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上面(這種老古董的系統大家就別用了吧?。瑩f在IOS7上面已經得到修復。不過現實是目前在處理屬性文本中含有阿拉伯文時,IOS系統的表現就是不穩定。
既然是這樣,那一種處理方法就是將文本中的阿拉伯文過濾掉了,替換成空格或者其它什么的。以便使用不包含阿拉伯文的文本來計算size。
需要如何替換?
這里就要用到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?;蛟S這個問題還有更好的解決方案,各位如果知道,不妨告訴我。。
</p>