GCD 块不更新 NSCollectionView

Posted

技术标签:

【中文标题】GCD 块不更新 NSCollectionView【英文标题】:GCD blocks not updating NSCollectionView 【发布时间】:2010-07-30 23:40:10 【问题描述】:

我有一个 Cocoa 应用程序,它监听通知并将更新发布到由 NSCollectionView 监控的 NSMutableArray。通知大量到达,因此我正在考虑使用不同的队列来处理它们并相应地更新数组。

现在我正在使用addObserverForName:object:queue:usingBlock 注册通知,当我为队列指定[NSOperationQueue mainQueue] 时,它工作正常(数组和NSCollectionView 都已更新)。但是,当我创建自己的队列(使用[[NSOperationQueue alloc] init])时,NSCollectionView 将停止更新。使用调试器,我可以看到它正在监视的数组正在更新。

这是一个错误,还是我在这里遗漏了什么?

【问题讨论】:

【参考方案1】:

在使用 AppKit 绑定时,发布的任何 KVO 通知都需要在主线程上发生,才能正常工作。因此,如果您直接从后台线程中的通知处理程序修改数组,则 NSCollectionView 将在该线程而不是主线程上接收任何触发的 KVO 通知。发生这种情况时的行为是未定义的,充其量不会起作用,而最坏的情况可能会导致崩溃或其他奇怪的行为。

如果通知的数量确实足够多,以至于更新每个通知都会导致性能问题,我会推荐以下两种方法之一:

查看NSNotificationQueue(与 NSOperationQueue 无关),它支持将多个已发布的 NSNotification 合并为一个发送给观察者的通知。 像您正在做的那样在后台收听通知,但您自己批量更改,可能只发布每第 N 个更改,或者如果在 X 时间内没有更多更新,则使用计时器触发发布更新。然后,当您对数组执行实际更新时,尝试将其缩小到尽可能少的工作,然后将其放在主线程上。在 mainQueue 上调用 -[NSOperationQueue addOperationWithBlock:] 是一种简单的方法。

【讨论】:

以上是关于GCD 块不更新 NSCollectionView的主要内容,如果未能解决你的问题,请参考以下文章

当我以编程方式制作滑块时,为啥滑块不更新标签?

滑块不起作用并更新图表中的值

如何在目标 c 中使用 GCD dispatch_async 调用/编写以下方法

透明 NSCollectionView 背景

NSCollectionView 拖放:大多数委托事件没有被调用

NSCollectionView 斯威夫特