NSAttributedString初始化抛出NSRangeException

时间:2015-04-07 04:22:45

标签: ios swift nsattributedstring

我写了一个简单的扩展来解码html实体:

extension String {
    func htmlDecode() -> String {
        if let encodedData = self.data(using: String.Encoding.unicode) {
            let attributedString = try! NSAttributedString(data: encodedData, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.unicode], documentAttributes: nil)
            return attributedString.string
        }
        return self
    }
}

现在它在行if let attributedString …上抛出错误:

  

***由于未捕获的异常'NSRangeException'终止应用,原因:'*** - [__ NSArrayM objectAtIndex:]:索引4超出边界[0 .. 2]'

并且self不是零或者其他东西,只有String这样:

self = (String) "...über 25'000 Franken..."

这个奇怪的NSArray - 异常来自哪里?

5 个答案:

答案 0 :(得分:2)

在黑暗中拍摄:你确定初始化发生在主线程上吗?

我有完全相同的问题。我注意到在我的情况下,异常发生在可重现的条件下(UICollectionViewController中的动画),但我无法找到实际原因。我最好的猜测是它是一个框架错误,所以我也建议你提交雷达。

我最终将HTML格式的字符串预先渲染到缓存(又称数组)中,然后根据需要从中加载NSAttributedStrings。

请注意,此解决方案可能不适合您的用例,因为我只需要一次处理有限数量的格式化字符串,因此知道提前呈现它们的费用。

答案 1 :(得分:0)

看起来像一个bug,可能与Swift字符串处理字符的方式有所不同,而不是NSString

我会提出雷达。

答案 2 :(得分:0)

在我的情况下,发生这种情况是因为我试图从处于分离状态的NSAttributedString中实例化UICollectionViewCell(在将其插入父UICollectionView之前)。

答案 3 :(得分:0)

DispatchQueue.main.async { let text = yourHtmlText.htmlDecode() }

答案 4 :(得分:-1)

我只是因为一个不同的错误而错过了这个错误:

  

***由于未捕获的异常终止应用程序' NSInvalidArgumentException',原因:' - [_ SwiftValue unsignedIntegerValue]:无法识别的选择器发送到实例0x60000024b790'

在这段代码中发现了一个严重错误:

我正在将String.Encoding.unicode - 一个Swift值 - 传递给一个使应用程序崩溃的Objective-C方法。使用String.Encoding.unicode.rawValue后,崩溃消失了:

extension String {
    func htmlDecode() -> String {
        if let encodedData = self.data(using: String.Encoding.unicode) {
            if let attributedString = try? NSAttributedString(data: encodedData, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.unicode.rawValue], documentAttributes: nil) {
                return attributedString.string
            }
        }
        return self
    }
}