SIGABRT when using NSAttributedString.DocumentType.html

I have been battling with a problem that is completely and utterly perplexing to me. Swift 4, High Sierra 10.13.6, Xcode 9.4.1 (9F2000).


I have a view-based NSTable. In each cell is an NSTextField which I am trying to populate with arbitrary HTML for formatting. In effect it is a "chat view" for a Matrix client I am working on.


The Apple documentation suggests I can just give it some HTML and it will convert into an attributed string, so I have effectively done that by extending

String
and adding
func toAttributedStringFromHTML(justify: NSTextAlignment) -> NSAttributedString:


guard let data = data(using: .utf16, allowLossyConversion: true) else { return NSAttributedString() }
let str: NSMutableAttributedString = try NSMutableAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil)


This is called from the table cell setup:


    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
    ...
               cellAttributedStringValue = (event.content["formatted_body"] as! String).trimmingCharacters(in: .whitespacesAndNewlines).toAttributedStringFromHTML(justify: .left)


This often works fine, but occasionally it crashes with a SIGABRT. The stack trace points to an NSInternalInconsistencyException but Xcode points to the

let str: NSMutableAttributedString = try NSMutableAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil)
line.


The stack trace is exceptionally long, but looks like this:


2018-08-08 22:31:54.168731+0100 Seaglass[67287:21638720] *** Assertion failure in -[NSTableRowData insertRowsAtIndexes:withRowAnimation:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1561.60.100/TableView.subproj/NSTableRowData.m:7470
2018-08-08 22:31:54.173683+0100 Seaglass[67287:21638720] [General] An uncaught exception was raised
2018-08-08 22:31:54.173718+0100 Seaglass[67287:21638720] [General] insertRowsAtIndexes:withRowAnimation: can not happen while updating visible rows!
2018-08-08 22:31:54.173849+0100 Seaglass[67287:21638720] [General] (
  0   CoreFoundation                      0x00007fff389102db __exceptionPreprocess + 171
  1   libobjc.A.dylib                     0x00007fff5fab1c76 objc_exception_throw + 48
  2   CoreFoundation                      0x00007fff38916072 +[NSException raise:format:arguments:] + 98
  3   Foundation                          0x00007fff3aa3f340 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 193
  4   AppKit                              0x00007fff35f22273 -[NSTableRowData insertRowsAtIndexes:withRowAnimation:] + 304
  5   AppKit                              0x00007fff35f21ffa -[NSTableView _doUpdatedWorkWithHandler:] + 106
  6   AppKit                              0x00007fff35f21e72 -[NSTableView insertRowsAtIndexes:withAnimation:] + 162
  7   AppKit                              0x00007fff3611209d -[NSTableView noteNumberOfRowsChanged] + 198
  8   Seaglass                            0x00000001000121ba _T08Seaglass22MainViewRoomControllerC09matrixDidD7MessageySo7MXEventC5event_14SwiftMatrixSDK19MXTimelineDirectionO9directionSo11MXRoomStateC04roomR0tFTf4gddn_n + 2714
  9   Seaglass                            0x000000010000bf72 _T08Seaglass22MainViewRoomControllerCAA06MatrixD8DelegateA2aDP09matrixDidD7MessageySo7MXEventC5event_05SwiftF3SDK19MXTimelineDirectionO9directionSo11MXRoomStateC04roomS0tFTW + 18
  10  Seaglass                            0x0000000100024208 _T08Seaglass14MatrixServicesC15subscribeToRoomySS6roomId_tFySo7MXEventC_05SwiftB3SDK19MXTimelineDirectionOSo11MXRoomStateCtcfU_Tf4gngnn_n + 4360
  11  Seaglass                            0x0000000100022612 _T08Seaglass14MatrixServicesC15subscribeToRoomySS6roomId_tFySo7MXEventC_05SwiftB3SDK19MXTimelineDirectionOSo11MXRoomStateCtcfU_TA + 34
  12  SwiftMatrixSDK                      0x0000000100d183cc _T0So15MXEventTimelineC14SwiftMatrixSDKE14listenToEventsypSayAC0A4TypeOGSg_ySo0A0C_AC19MXTimelineDirectionOSo11MXRoomStateCtctFyAJSg_SC02__jK0VANSgtcfU_TA + 76
  13  SwiftMatrixSDK                      0x0000000100d1820a _T0So7MXEventCSgSC21__MXTimelineDirectionVSo11MXRoomStateCSgIegxyx_AceHIeyByyy_TR + 74
  14  SwiftMatrixSDK                      0x0000000100c48d22 -[MXEventListener notify:direction:andCustomObject:] + 162
  15  SwiftMatrixSDK                      0x0000000100c4d06a -[MXEventTimeline notifyListeners:direction:] + 407
  16  SwiftMatrixSDK                      0x0000000100c4c0ea -[MXEventTimeline addEvent:direction:fromStore:isRoomInitialSync:] + 1022
  17  SwiftMatrixSDK                      0x0000000100c4ba8d -[MXEventTimeline handlePaginationResponse:direction:] + 306
  18  SwiftMatrixSDK                      0x0000000100c4a78f __69-[MXEventTimeline paginate:direction:onlyFromStore:complete:failure:]_block_invoke + 177
  19  libdispatch.dylib                   0x0000000101a17cae _dispatch_call_block_and_release + 12
  20  libdispatch.dylib                   0x0000000101a0fd8f _dispatch_client_callout + 8
  21  libdispatch.dylib                   0x0000000101a1be09 _dispatch_main_queue_callback_4CF + 549
  22  CoreFoundation                      0x00007fff388c8c19 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
  23  CoreFoundation                      0x00007fff3888adfa __CFRunLoopRun + 2586
  24  CoreFoundation                      0x00007fff3888a153 CFRunLoopRunSpecific + 483
  25  UIFoundation                        0x00007fff5c581f03 -[NSHTMLReader _loadUsingWebKit] + 1902
  26  UIFoundation                        0x00007fff5c584e86 -[NSHTMLReader attributedString] + 22
  27  UIFoundation                        0x00007fff5c4f43a8 _NSReadAttributedStringFromURLOrData + 12388
  28  UIFoundation                        0x00007fff5c4f12b0 -[NSAttributedString(NSAttributedStringUIFoundationAdditions) initWithData:options:documentAttributes:error:] + 117
  29  Seaglass                            0x0000000100034d9d _T0So25NSMutableAttributedStringCAB10Foundation4DataV4data_s10DictionaryVySo012NSAttributedC0C6AppKitE24DocumentReadingOptionKeyVypG7optionss33AutoreleasingUnsafeMutablePointerVySo12NSDictionaryCSgGSg18documentAttributestKcfcTOTf4gXnnn_n + 173
  30  Seaglass                            0x00000001000350ca _T0SS8SeaglassE26toAttributedStringFromHTMLSo012NSAttributedD0CSC15NSTextAlignmentO7justify_tFTf4nx_n + 682
  31  Seaglass                            0x0000000100033ad9 _T0SS8SeaglassE26toAttributedStringFromHTMLSo012NSAttributedD0CSC15NSTextAlignmentO7justify_tF + 9
  32  Seaglass                            0x0000000100014ee9 _T08Seaglass22MainViewRoomControllerC05tableC0So6NSViewCSgSo07NSTableC0C_So0H6ColumnCSg7viewForSi3rowtFTf4gdnn_n + 5769
  33  Seaglass                            0x000000010000b82d _T08Seaglass22MainViewRoomControllerC05tableC0So6NSViewCSgSo07NSTableC0C_So0H6ColumnCSg7viewForSi3rowtFTo + 61
  34  AppKit                              0x00007fff35fb279b -[NSTableView(NSTableViewViewBased) _delegate_viewForTableColumn:row:] + 86
  35  AppKit                              0x00007fff35f2cec4 -[NSTableView(NSTableViewViewBased) makeViewForTableColumn:row:] + 87
  36  AppKit                              0x00007fff35f2c747 -[NSTableRowData _addViewToRowView:atColumn:row:] + 342
  37  AppKit                              0x00007fff35f2c421 -[NSTableRowData _addViewsToRowView:atRow:] + 211
  38  AppKit                              0x00007fff35f2aaa4 -[NSTableRowData _initializeRowView:atRow:] + 397
  39  AppKit                              0x00007fff3681696a -[NSTableRowData _preparedRowViewForRow:storageHandler:] + 154
  40  AppKit                              0x00007fff35f28ed1 -[NSTableRowData _addRowViewForVisibleRow:withPriorView:] + 392
  41  AppKit                              0x00007fff35f28c94 -[NSTableRowData _addRowViewForVisibleRow:withPriorRowIndex:inDictionary:withRowAnimation:] + 416
  42  AppKit                              0x00007fff36818ba3 -[NSTableRowData _updateVisibleRowEntries] + 1906
  43  AppKit                              0x00007fff368194d3 __59-[NSTableRowData _automaticRowHeightsUpdateVisibleRowViews]_block_invoke.1494 + 97
  44  AppKit                              0x00007fff368190ad -[NSTableRowData _keepTopRowStable:andDoWorkUntilDone:] + 535
  45  AppKit                              0x00007fff3681941d -[NSTableRowData _automaticRowHeightsUpdateVisibleRowViews] + 161
  46  AppKit                              0x00007fff35f27971 -[NSTableRowData updateVisibleRowViews] + 261
  47  AppKit                              0x00007fff35f27163 -[NSTableView layout] + 206
  48  AppKit                              0x00007fff366d0ad0 _NSViewLayout + 587
  49  AppKit                              0x00007fff35ecaeff -[NSView _layoutSubtreeWithOldSize:] + 437
  50  AppKit                              0x00007fff35ecb178 -[NSView _layoutSubtreeWithOldSize:] + 1070
  51  AppKit                              0x00007fff35ecb178 -[NSView _layoutSubtreeWithOldSize:] + 1070I                              0x00007fff35ecb178 -[NSView _layoutSubtreeWithOldSize:] + 1070
  53  AppKit                              0x00007fff35ecb178 -[NSView _layoutSubtreeWithOldSize:] + 1070
  54  AppKit                              0x00007fff35ecb178 -[NSView _layoutSubtreeWithOldSize:] + 1070
  55  AppKit                              0x00007fff35ecb178 -[NSView _layoutSubtreeWithOldSize:] + 1070
  56  AppKit                              0x00007fff35ecb178 -[NSView _layoutSubtreeWithOldSize:] + 1070
  57  AppKit                              0x00007fff366d782c -[NSView _layoutSubtreeIfNeededAndAllowTemporaryEngine:] + 1380
  58  AppKit                              0x00007fff35ee86ef -[NSWindow(NSConstraintBasedLayout) _layoutViewTree] + 163
  59  AppKit                              0x00007fff35f53e83 -[NSWindow(NSConstraintBasedLayout) layoutIfNeeded] + 268
  60  AppKit                              0x00007fff36705443 ___NSWindowGetDisplayCycleObserver_block_invoke.5896 + 67
  61  AppKit                              0x00007fff35f6455e __37+[NSDisplayCycle currentDisplayCycle]_block_invoke + 695
  62  QuartzCore                          0x00007fff43bfb8c7 _ZN2CA11Transaction19run_commit_handlersE18CATransactionPhase + 49
  63  QuartzCore                          0x00007fff43bfa389 _ZN2CA11Transaction6commitEv + 171
  64  AppKit                              0x00007fff3671ca72 __65+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayRefresh]_block_invoke + 283
  65  CoreFoundation                      0x00007fff388a8417 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
  66  CoreFoundation                      0x00007fff388a833f __CFRunLoopDoObservers + 527
  67  CoreFoundation                      0x00007fff3888a8b8 __CFRunLoopRun + 1240
  68  CoreFoundation                      0x00007fff3888a153 CFRunLoopRunSpecific + 483
  69  HIToolbox                           0x00007fff37b74d96 RunCurrentEventLoopInMode + 286
  70  HIToolbox                           0x00007fff37b74b06 ReceiveNextEventCommon + 613
  71  HIToolbox                           0x00007fff37b74884 _BlockUntilNextEventMatchingListInModeWithFilter + 64
  72  AppKit                              0x00007fff35e25a73 _DPSNextEvent + 2085
  73  AppKit                              0x00007fff365bbe34 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 3044
  74  AppKit                              0x00007fff35e1a885 -[NSApplication run] + 764
  75  AppKit                              0x00007fff35de9a72 NSApplicationMain + 804
  76  Seaglass                            0x0000000100003f69 main + 9
  77  libdyld.dylib                       0x00007fff606cb015 start + 1
  78  ???                                 0x0000000000000003 0x0 + 3
)


This doesn't make sense. As best as I can tell, this is all happening on the main thread.


Is this an actual bug or am I doing something stupid?


If seeing more of the codebase will help:

https://github.com/neilalexander/seaglass/blob/08c531f643245143cc2794bff738356b4241da1b/Seaglass/Extension/String.swift

https://github.com/neilalexander/seaglass/blob/08c531f643245143cc2794bff738356b4241da1b/Seaglass/Controller/MainViewRoomController.swift

Replies

I'm getting the crash:
Crashing on exception: insertRowsAtIndexes:withRowAnimation: can not happen while updating visible rows!
I accumulate changes to my table and then set them all at once via a timer.
However, the timer is firing during a run loop inside NSHTMLReader _loadUsingWebKit.
This is EXCEEDINGLY inconvenient for me.
I am unsure how I am supposed to tell if my timer can modify the values of the table or not.