NSMutableAttributedString致命异常:NSRangeException

时间:2016-02-03 10:20:13

标签: ios crash nsrange nsmutableattributedstring nsrangeexception

当我尝试将属性应用于子字符串时,我有时会在以下代码中崩溃:

// Dummy strings
let originalString = "Some example string"
let searchSubString = "exam"

// Get range of sub-string for which new attributes are to be set.
let rangeOfSubString: NSRange = (originalString.lowercaseString as NSString).rangeOfString(searchSubString.lowercaseString)

// Apply new attributes to the sub-string in original string and show it in UILabel.
let attributedOriginalString = NSMutableAttributedString(string: originalString, attributes: [NSForegroundColorAttributeName : UIColor.blueColor()])
attributedOriginalString.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(14.0), range: rangeOfSubString)
attributedOriginalString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: rangeOfSubString)
self.textLabel.attributedText = attributedOriginalString

以下是堆栈跟踪:

Thread : Fatal Exception: NSRangeException
0 CoreFoundation 0x26cbefef __exceptionPreprocess
1 libobjc.A.dylib 0x35362c8b objc_exception_throw
2 CoreFoundation 0x26cbef35 -[NSException initWithCoder:]
3 Foundation 0x2793ac3b -[NSRLEArray objectAtIndex:effectiveRange:]
4 Foundation 0x27954b2d -[NSConcreteMutableAttributedString addAttribute:value:range:]

我无法复制它,但我通过崩解剂得到了这个崩溃日志。

崩溃日志似乎表明rangeOfSubString超出了originalString的范围,但我认为它不会发生。

任何人都可以指出崩溃的原因是什么?

1 个答案:

答案 0 :(得分:0)

如果其他人遇到这样的问题,请发布我的答案:

替换

let rangeOfSubString: NSRange = (originalString.lowercaseString as NSString).rangeOfString(searchSubString.lowercaseString)

let rangeOfSubString: NSRange = (originalString as NSString).rangeOfString(searchSubString, options: .CaseInsensitiveSearch)

计算子字符串范围的第一种方法是错误的原因:

  • 正在计算子字符串范围WRT小写版本,并将该范围的属性应用于原始字符串(非小写)。 但是在特殊字符的情况下,使用上述方法计算的范围可能超出原始字符串范围,导致小写字符可能需要比大写版本更长的长度,反之亦然。

    ,大写土耳其语字符“İ”的长度为1,而小写字母“i̇”的长度为2。

  • 对于前。 如果我们在“Hİ”(长度= 2)中搜索“İ”,第一种方法会给你一个范围(1,2)因为“İ”以小写形式要求长度= 2,但是如果你应用范围(1,2) )对于“Hİ”,它将超出范围(0,2)的范围,或者如果原始字符串中有更多字符,如“Hİabc”,则它将对应于“İa”,这又是错误的。

  • 所以计算范围WRT原始字符串,稍后我需要将该范围应用于原始字符串本身。

另见apple的文档:

  

lowercaseString:

     

不保证案例转换   对称或产生与长度相同的弦   原稿。

     

lcString = [myString lowercaseString];

     

可能不等于此   语句:

     

lcString = [[myString uppercaseString] lowercaseString];

     

例如,   德语中“ß”的大写形式是“SS”,所以将“Straße”转换为   大写,然后是小写,产生这个字符串序列:

     

“大街”

     

“STRASSE”

     

“大街”

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/#//apple_ref/occ/instp/NSString/lowercaseString