NSOutlineView produces error "encountered thread with uncommitted CATransaction" after reloadData()

I have an NSOutlineView that's populated by an array from my AppDelegate. The tableCellViews are subclassed to provide more NSImageViews and NSTextFields for UI.


I fill the array of my own classes from a [NSURL] on a background thread:


dispatch_barrier_async(search_queue, { () -> Void in
     ..
})


At the end of the fill-loop, I reload the NSOutlineView:


dispatch_sync(dispatch_get_main_queue(), { () -> Void in
                self.performSelector(#selector(AppDelegate.unsetForBackgroundTask), withObject: nil, afterDelay: 0.1)
})


I'm doing a performSelector after 0.1 sec in an attempt to stop the following error:


2016-06-23 23:33:18.752 myApp[15145:397335] Unexpected outstanding background CATransaction

CoreAnimation: warning, encountered thread with uncommitted CATransaction; created by:

0 QuartzCore 0x00007fff9915169a _ZN2CA11Transaction4pushEv + 318

1 QuartzCore 0x00007fff9915119a _ZN2CA11Transaction15ensure_implicitEv + 276

2 QuartzCore 0x00007fff99157719 _ZN2CA5Layer13thread_flags_EPNS_11TransactionE + 37

3 QuartzCore 0x00007fff99157668 _ZN2CA5Layer4markEPNS_11TransactionEjj + 64

4 QuartzCore 0x00007fff9915912b _ZN2CA5Layer25set_needs_display_in_rectERK6CGRect + 333

5 QuartzCore 0x00007fff99158fdc -[CALayer setNeedsDisplayInRect:] + 25

6 AppKit 0x00007fffa15f92e8 _NSBackingLayerSetNeedsDisplayInRect + 319

7 AppKit 0x00007fffa15f91a3 -[_NSBackingLayer setNeedsDisplayInRect:] + 61

8 AppKit 0x00007fffa16d949e -[_NSTextViewBackingLayer setNeedsDisplayInRect:] + 262

9 AppKit 0x00007fffa15f998b -[NSView(NSInternal) _setLayerNeedsDisplayInViewRect:] + 606

10 AppKit 0x00007fffa15c788e NSViewSetNeedsDisplayInRect + 945

11 AppKit 0x00007fffa15c74d6 -[NSView setNeedsDisplayInRect:] + 48

12 AppKit 0x00007fffa16b2367 -[NSTextView setNeedsDisplayInRect:avoidAdditionalLayout:] + 1103

13 UIFoundation 0x00007fff8f845e3f -[NSLayoutManager _primitiveInvalidateDisplayForGlyphRange:] + 4767

14 UIFoundation 0x00007fff8f846ab2 -[NSLayoutManager invalidateDisplayForCharacterRange:] + 458

15 UIFoundation 0x00007fff8f940d15 -[NSLayoutManager(NSPrivate) _setExtraLineFragmentRect:usedRect:textContainer:] + 514


But it's not working - niether does simply calling reloadData() straight away in the main queue dispatch. If the array's filled with a couple of thousand items then this error appears and the app grinds to a halt the minute I try and scroll down the outline view. Am I barking up the wrong tree in assuming it's something to do with my NSOutlineView?

Replies

Are you sure this is the only point at which the data model for the outline view is affected? I'm assuming you don't have that outline view set up with bindings, right? That would affect things too…

Hi Bob,


Yep the dispatched loop is the only one that does it. Are you saying that I should try the bindings instead?

No, it wouldn't be worth it to tear out everything you already have and replace it with bindings.


Okay, so that's not it… Maybe comment out that updating code to see if it's really the source of the lines? It could be something else for all we know.

I think I found it: I was updating the UI when the user escaped from the fill loop to indicate that no more items would be added. And I'd neglected to put that line into a dispatch to main thread block!


Hence it only happened occasionally during testing. Hand slaps head.


Thanks for leading me gently by the hand, though!

My pleasure. Yeah, dispatch and threads can be hard to get right even for experienced programmers. Good luck moving forward! 🙂