NSMutableAttributedString initialisation to prevent crash

We keep getting intermittent app crash from our customers and it is related to initialisation of NSMutableAttributedString.


Code:

let result = try NSMutableAttributedString(data: data, options: htmlOptions, documentAttributes: nil) <- Crash here

The above code is executed in cellForRowAt inside a TableViewCell and in some code also in viewDidLoad of a view.

data only contains short html text or sometimes even empty string "".

We also cannot reproduce the issue when testing with simulator and our test devices.


If I google this issue, it seems like there is no official solution that really worked.

Suggestions to run in main thread or run in background and then post in main thread seems to contradict the description in the documentation about NSMutableAttributedString.


The HTML importer should not be called from a background thread (that is, the options dictionary includes NSDocumentTypeDocumentAttribute with a value of NSHTMLTextDocumentType). It will try to synchronize with the main thread, fail, and time out. Calling it from the main thread works (but can still time out if the HTML contains references to external resources, which should be avoided at all costs). The HTML import mechanism is meant for implementing something like markdown (that is, text styles, colors, and so on), not for general HTML import.


Any recommendation on how to use NSMutableAttributedString properly without running into this crash?


Here is the crash logs:

Fatal Exception: NSInternalInconsistencyException

0 CoreFoundation 0x1b3a9c518 __exceptionPreprocess

1 libobjc.A.dylib 0x1b2c779f8 objc_exception_throw

2 CoreFoundation 0x1b39b6148 +[_CFXNotificationTokenRegistration keyCallbacks]

3 Foundation 0x1b44c5f5c -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:]

4 UIKitCore 0x1e000d9b0 _prepareForCAFlush

5 UIKitCore 0x1e003a674 _beforeCACommitHandler

6 CoreFoundation 0x1b3a2d89c __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__

7 CoreFoundation 0x1b3a285c4 __CFRunLoopDoObservers

8 CoreFoundation 0x1b3a28b40 __CFRunLoopRun

9 CoreFoundation 0x1b3a28354 CFRunLoopRunSpecific

10 UIFoundation 0x1be08fc78 -[NSHTMLReader _loadUsingWebKit]

11 UIFoundation 0x1be092bfc -[NSHTMLReader attributedString]

12 UIFoundation 0x1be0deb88 _NSReadAttributedStringFromURLOrData

13 UIFoundation 0x1be092b38 -[NSAttributedString(NSAttributedStringUIFoundationAdditions) initWithData:options:documentAttributes:error:]

14 MyApp 0x10140b140 @nonobjc NSMutableAttributedString.init(data:options:documentAttributes:) (<compiler-generated>)

Answered by DTS Engineer in 356326022

I really need the info that such a report contains

Someone else sent me an Apple crash report and that let me refresh my understanding of this issue. 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.

  • Alternatively, consider using the Markdown support we added in macOS 12 and iOS 15. For the details, watch WWDC 2021 Session 10109 What’s new in Foundation.

IMPORTANT Foundation’s Markdown support is strongly integrated with SwiftUI but it’s not limited to SwiftUI, or even to Swift. It’s compatible with other UI frameworks and Objective-C.

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

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Do you have a hint of what could be going wrong here?

No, sorry.

Can you isolate this into a small test project? If so, you could try opening a DTS tech support incident to see if someone is up for digging into this. It’s possible that your library is doing something wrong and that’s triggering this problem. OTOH, it’s also possible that both your code and your client’s code are just an innocent bystanders.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

What do you mean?

This was discussed in WWDC 2021 Session 10109 What’s new in Foundation. As the session title suggests, it’s not limited to SwiftUI.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Facing same issue in ios 15.2.1. Is this issue resolve?

Still happening here

Sadly, that’s expected. I’ve updated my response with more details and marked it as Apple Recommended.

Speaking personally, I wouldn’t build an app that relies on this feature. This bug has been around for years now — many more years than this thread, and it’s already 3 years old!

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I am trying to convert HTML to attributed string so used this try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)

But, am getting memory leak in this single line and due to memory leak app crashes.. Any solution for this??

In case it can help someone. There was no problem in my project. But starting with XCode 15.3, the crash always occurred on the device, never on the simulator. For project reasons we could not modify it. I found that if in Edit Scheme -> Diagnostics, I disable the Malloc Stack Logging option, it works again on the device. I don't know what's going on but in case it can be of help.

NSMutableAttributedString initialisation to prevent crash
 
 
Q