Блоки GCD не обновляют NSCollectionView - PullRequest
0 голосов
/ 31 июля 2010

У меня есть приложение Cocoa, которое прослушивает уведомления и публикует обновления на NSMutableArray, отслеживаемом NSCollectionView. Уведомления приходят большими объемами, поэтому я подумал об использовании другой очереди для их обработки и соответствующего обновления массива.

Прямо сейчас я использую addObserverForName:object:queue:usingBlock для регистрации уведомлений, и она отлично работает (обновляются и массив, и NSCollectionView), когда я указал [NSOperationQueue mainQueue] для очереди. Однако когда я создал собственную очередь (используя [[NSOperationQueue alloc] init]), NSCollectionView перестает обновляться. Используя отладчик, я вижу, что обновляемый массив обновляется.

Это ошибка, или я что-то здесь упустил?

1 Ответ

3 голосов
/ 31 июля 2010

При работе с привязками AppKit любые уведомления KVO, которые публикуются, должны появляться в главном потоке, чтобы все работало правильно.Таким образом, если вы измените массив непосредственно из вашего обработчика уведомлений в фоновом потоке, NSCollectionView будет получать любые инициированные уведомления KVO в этом потоке, а не в основном потоке.Поведение, когда это происходит, не определено, и в лучшем случае не будет работать, в то время как в худшем случае может вызвать сбои или другое странное поведение.

Если уведомления приходят в достаточно больших количествах, то обновление при каждом уведомлении является производительностьюпроблема, я бы порекомендовал одну из двух вещей:

  • Взгляните на NSNotificationQueue (не имеет отношения к NSOperationQueue), который поддерживает объединение нескольких опубликованных NSNotifications в одно уведомление, отправленное наваш наблюдатель.
  • Слушайте уведомления в фоновом режиме, как вы делаете, но собирайте изменения самостоятельно, возможно, публикуйте только каждое N-е изменение или запускайте таймер, чтобы опубликовать обновление, если больше не поступило вX количество времени.Затем, когда вы выполняете фактическое обновление массива, постарайтесь сузить его до минимума, насколько это возможно, затем перенесите это в основной поток.Вызов -[NSOperationQueue addOperationWithBlock:] в mainQueue - это простой способ сделать это.
...