Initialization of NSAttributedString is crashing application

Viewed 3296

Below code is crashing(not always but rarely) despite the fact that it is inside do-catch block. Fabric crashlytics states that exception is Fatal Exception: NSInternalInconsistencyException and sometimes this 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()
}

While I read apple docs of NSAttributedString it states that it should be on main thread so I surround it with Dispatch.main.async block but doing this is not setting the styles that are set on NSAttributedString

3 Answers

As per the resolution provided by apple developer forum here : https://forums.developer.apple.com/thread/115405

Sadly, this is a known bug in iOS (r. 23592459) that can potentially affect anyone who constructs an NSAttributedString from HTML.

There isn’t a good workaround for this other than to avoid this API altogether. My advice:

If you’re displaying large chunks of complex HTML, use a WKWebView.

If this HTML is highly constrained — perhaps you’re just using HTML as an easy way to transfer a constrained set of attributes, like bold and italics — create your own markup system that doesn’t relying on HTML. Or parse the HTML for just these attributes and use the result to create your attributed string.

I’m sorry I don’t have better news here.

So, to avoid the crash, you might need to avoid using NSAttributedString( data: function itself and write your own way to parse the html.

Update the UI only in Main Thread.

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

If you are trying to convert HTML to String, you can use the extension on String as below:

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 ?? ""
    }
}
Related