views:

41

answers:

1

I have a Cocoa app that listens for notification and posts updates to an NSMutableArray monitored by a NSCollectionView. The notifications arrive in large volumes so I was thinking to use a different queue to process them and update the array accordingly.

Right now I am using addObserverForName:object:queue:usingBlock to register for notifications, and it works fine (both the array and NSCollectionView are updated) when I specified [NSOperationQueue mainQueue] for the queue. However when I created my own queue (using [[NSOperationQueue alloc] init]), then the NSCollectionView stops updating. Using the debugger I can see the array it's monitoring is being updated though.

Is this a bug, or did I miss something here?

+2  A: 

When working with AppKit bindings, any KVO notifications that get posted need to happen on the main thread in order for things to work correctly. So, if you modify the array directly from your notification handler in a background thread, the NSCollectionView will receive any triggered KVO notifications on that thread and not the main thread. The behavior when this happens is undefined, and at best won't work, while at worst could cause crashes or other strange behavior.

If the notifications do come in large enough quantities that updating on every notification is a performance problem, I'd recommend one of two things:

  • Take a look at NSNotificationQueue (no relation to NSOperationQueue), which supports coalescing multiple posted NSNotifications into a single notification sent to your observer.
  • Listen for the notifications in the background like you're doing, but batch up the changes yourself, perhaps posting only every Nth change or having a timer fire to post an update if no more have arrived in X amount of time. Then when you perform the actual update on the array, try to narrow that down to as little work as possible, then put that work on the main thread. Calling -[NSOperationQueue addOperationWithBlock:] on the mainQueue is an easy way to do that.
Brian Webster