21

I have an extension to convert HTML string to NSAttributedString.

After iOS 15 is released, I've seen a lot of crashes from my user. All those crashes are on iOS 15 and occur on the main thread.

Here is a typical crash report from Crashlytics.

Crashed: com.apple.main-thread
0  libsystem_platform.dylib       0x1f29d60c0 _os_unfair_lock_recursive_abort + 36
1  libsystem_platform.dylib       0x1f29d0a10 _os_unfair_lock_lock_slow + 304
2  Foundation                     0x183d5e730 -[NSProcessInfo(NSProcessInfoHardwareState) isLowPowerModeEnabled] + 68
3  WebCore                        0x192011004 <redacted> + 56
4  CoreFoundation                 0x182535ee8 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 28
5  CoreFoundation                 0x1825d1b9c ___CFXRegistrationPost_block_invoke + 52
6  CoreFoundation                 0x1825a4f54 _CFXRegistrationPost + 456
7  CoreFoundation                 0x18254bd54 _CFXNotificationPost + 716
8  Foundation                     0x183d50028 -[NSNotificationCenter postNotificationName:object:userInfo:] + 96
9  Foundation                     0x183dc89d4 NSProcessInfoNotifyPowerState + 188
10 Foundation                     0x183d5e768 -[NSProcessInfo(NSProcessInfoHardwareState) isLowPowerModeEnabled] + 124
11 WebCore                        0x191595118 <redacted> + 96
12 WebCore                        0x19201116c WebCore::LowPowerModeNotifier::LowPowerModeNotifier(WTF::Function<void (bool)>&&) + 52
13 WebCore                        0x192f36c4c WebCore::Page::Page(WebCore::PageConfiguration&&) + 1848
14 WebKitLegacy                   0x1a605ae34 -[WebView(WebPrivate) _commonInitializationWithFrameName:groupName:] + 3060
15 WebKitLegacy                   0x1a605a214 -[WebView(WebPrivate) _initWithFrame:frameName:groupName:] + 116
16 UIFoundation                   0x18d306028 -[NSHTMLReader _loadUsingWebKit] + 832
17 UIFoundation                   0x18d30715c -[NSHTMLReader attributedString] + 32
18 UIFoundation                   0x18d2c04e8 _NSReadAttributedStringFromURLOrData + 8420
19 UIFoundation                   0x18d2be378 -[NSAttributedString(NSAttributedStringUIFoundationAdditions) initWithData:options:documentAttributes:error:] + 156
20 MyAppExtensions                 0x108aa0fc4 _hidden#912_ + 4374482884 (__hidden#360_:4374482884)
21 MyAppExtensions                 0x108aa0894 NSAttributedString.init(htmlString:font:useDocumentFontSize:) + 36 (__hidden#925_:36)
22 MyAppName                           0x1045eca18 {foo_class}.convertHTML(_:) + 670 (xxxx.swift:670)
23 MyAppName                           0x1045e5c58 {foo_class}.some_function_3 + 620 (xxxx.swift:620)
24 MyAppName                           0x1045e4760 {foo_class}.some_function_2 + 212 (xxxx.swift:212)
25 MyAppName                           0x1045e4200 {foo_class}.some_function_1 + 138 (xxxx.swift:138)
.
.
.
42 UIKitCore                      0x184b5e1d0 _UIGestureRecognizerSendTargetActions + 116
43 UIKitCore                      0x184b2705c _UIGestureRecognizerSendActions + 284
44 UIKitCore                      0x184b60580 -[UIGestureRecognizer _updateGestureForActiveEvents] + 636
45 UIKitCore                      0x184b186fc _UIGestureEnvironmentUpdate + 1988
46 CoreFoundation                 0x18254c570 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 36
47 CoreFoundation                 0x18251b854 __CFRunLoopDoObservers + 572
48 CoreFoundation                 0x1825168ec __CFRunLoopRun + 1052
49 CoreFoundation                 0x18252a3c8 CFRunLoopRunSpecific + 600
50 GraphicsServices               0x19dd3b38c GSEventRunModal + 164
51 UIKitCore                      0x184ed00bc -[UIApplication _run] + 1100
52 UIKitCore                      0x184c4dbe8 UIApplicationMain + 2124
53 libswiftUIKit.dylib            0x199afe184 UIApplicationMain(_:_:_:_:) + 104
54 MyAppName                      0x1043a5894 main + 7 (main.swift:7)
55 dyld                           0x106b81a24 start

The following is code of converting HTML to NSAttributedString:

extension NSAttributedString {
  convenience public init(htmlString html: String, font: UIFont? = nil, useDocumentFontSize: Bool = true) throws {
    let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
      .documentType: NSAttributedString.DocumentType.html,
      .characterEncoding: String.Encoding.utf8.rawValue
    ]

    guard let data = html.data(using: .utf8, allowLossyConversion: true) else {
      self.init(string: "")
      return
    }

    guard let fontFamily = font?.familyName else {
      try self.init(data: data, options: options, documentAttributes: nil)
      return
    }

    let attr = try NSMutableAttributedString(data: data, options: options, documentAttributes: nil)

    let fontSize: CGFloat? = useDocumentFontSize ? nil : font!.pointSize
    let range = NSRange(location: 0, length: attr.length)
    attr.enumerateAttribute(.font, in: range, options: .longestEffectiveRangeNotRequired) { attrib, range, _ in
      if let htmlFont = attrib as? UIFont {
        let traits = htmlFont.fontDescriptor.symbolicTraits
        var descrip = htmlFont.fontDescriptor.withFamily(fontFamily)

        if (traits.rawValue & UIFontDescriptor.SymbolicTraits.traitBold.rawValue) != 0 {
          descrip = descrip.withSymbolicTraits(.traitBold)!
        }

        if (traits.rawValue & UIFontDescriptor.SymbolicTraits.traitItalic.rawValue) != 0 {
          descrip = descrip.withSymbolicTraits(.traitItalic)!
        }

        attr.addAttribute(.font, value: UIFont(descriptor: descrip, size: fontSize ?? htmlFont.pointSize), range: range)
      }
    }

    self.init(attributedString: attr)
  }

Btw, I'm using Xcode 12.5 to archive the release build.

8
  • 3
    I don't have an answer yet, but we build SDKs, and one of our customers has seen this exact crash because our SDK is using the low power mode notifications. We believe this is definitely an iOS 15 bug, but don't have any definite ways to reproduce it yet. I'll post back if we do find anything. Commented Sep 28, 2021 at 17:36
  • 1
    @CPR Thanks. I am still trying to reproduce it and find out if there is a way to avoid it. Commented Sep 28, 2021 at 21:27
  • 1
    I'm getting exactly the same crash here. I haven't been able to reproduce it yet. Confirming that the crash only happens on iOS 15, according to Firebase logs. Commented Oct 4, 2021 at 14:05
  • Any luck with reproducing above issue? Commented Oct 5, 2021 at 18:03
  • 1
    Do you have HTML string? Could you post it here as well? Commented Oct 10, 2021 at 11:37

2 Answers 2

2

Discussion about this crash in the apple developer forum here:

You might need to avoid using NSAttributedString(data: , options: [.documentType: NSAttributedString.DocumentType.html] itself and parse the HTML string to generate attribute string by yourself. Perhaps,you can use some open-source projects on GitHub such as DTCoreText.

Sign up to request clarification or add additional context in comments.

Comments

0

Malloc Stack Logging In case it's useful to anyone, disabling Malloc Stack Logging no longer causes my device to crash. Edit Scheme -> Diagnostics -> Uncheck the box.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.