NSAttributedString的初始化导致应用程序崩溃

8
以下代码虽然位于 do-catch 块中,但仍有可能崩溃(虽然不是总会)。Fabric Crashlytics 报告异常为 Fatal Exception: NSInternalInconsistencyException,有时也会出现 EXC_BAD_ACCESS KERN_PROTECTION_FAILURE 0x000000016fccb1f8
do {
    return try NSAttributedString(
        data: data,
        options: [
            .documentType:  NSAttributedString.DocumentType.html,
            .characterEncoding: String.Encoding.utf8.rawValue
        ],
        documentAttributes: nil
    )
} catch {
    return NSAttributedString()
}

我阅读了苹果关于NSAttributedString的文档,文档中指出应该在主线程上使用,因此我将其放在Dispatch.main.async块中,但是这样做并没有设置NSAttributedString上设置的样式。


你的数据是否有误? - Yevgeniy Leychenko
2
这似乎不可能,因为我无法复制该问题,并且根据应用中心的数据,成千上万的用户中只有58个用户遇到了这些崩溃。 - Yawar
3个回答

10
根据苹果开发者论坛提供的解决方案https://forums.developer.apple.com/thread/115405
不幸的是,这是iOS中已知的一个错误(r.23592459),可能会影响任何从HTML构造NSAttributedString的人。
除了完全避免使用此API外,没有更好的解决方法。我的建议:
如果您要显示大量复杂的HTML,请使用WKWebView。
如果这个HTML非常受限制——也许您只是使用HTML作为传输一组约束属性(如粗体和斜体)的简单方式——请创建自己的标记系统,不要依赖HTML。或者解析HTML以获取这些属性,并使用结果创建属性字符串。
很抱歉我在这里没有更好的消息。
因此,为了避免崩溃,您可能需要避免使用NSAttributedString(data:)函数本身,并编写自己的解析html的方式。

4

只在主线程中更新用户界面。

DispatchQueue.main.async {
    textLabel.attributedText = generateAttribString()
}

我尝试过这个,但是这样做并没有设置提供在nsattributedstring中的样式,只是设置了文本。 - Yawar
我想我会应用它并部署,然后注意这些崩溃是否消失。 - Yawar
@Yawar,崩溃问题修复了吗?你能确认一下它在你的应用中是否正常工作吗? - Arshad Shaik

0
如果您想将HTML转换为字符串,可以使用以下String扩展:
extension String {
    var htmlToAttributedString: NSAttributedString? {
        do {
            return try NSAttributedString(data: Data(utf8),
                                          options: [.documentType: NSAttributedString.DocumentType.html,
                                                    .characterEncoding: String.Encoding.utf8.rawValue],
                                          documentAttributes: nil)
        } catch {
            print("error: ", error)
            return nil
        }
    }
    var htmlToString: String {
        return htmlToAttributedString?.string ?? ""
    }
}

3
做的和原本一模一样,并且在大部分设备上都运行完美,但在某些设备上有时会崩溃。 - Yawar
可能的原因是您的数据不正确。在这段代码中,没有其他可能导致崩溃的原因。 - nikksindia
2
如果数据错误,应在catch块中处理。 - Yawar
在我的情况下,它不会执行,因为如果字符串没有转换为数据,则“Data(utf8)”可能会导致崩溃,并且它将不会进入catch块。 - nikksindia
数据的初始化如下:guard let data = htmlCSSString.data(using: .utf8) else { return NSAttributedString() } - Yawar
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接