5

在我的应用程序中,我有一个“主”NSPrivateQueueConcurrencyType上下文,它作为NSMainQueueConcurrencyType视图控制器依赖和传递的上下文的父级。我想这样做是为了利用异步保存(这个应用程序使用 iCloud 和 Core Data 并且保存做了很多工作来导出无处不在的日志)。设置类似于本文底部提到的 Zarra 方法

应用内的保存通常如下所示:

[context save:nil];
[context.parentContext performBlock:^{
     [context.parentContext save:nil];
}];

这似乎适用于小型编辑/更新,但我对删除许多对象时看到的内容感到困惑(例如,删除具有数百个与之相关的任务对象的项目)。

在这种情况下,保存是异步的,但看起来主线程进入了信号量等待情况(如我暂停调试器时所见)并被有效阻止(我无法在 UI 中滚动),直到后台私有上下文完成节省。

实际上,我只是注意到滑动删除单个对象会导致明显的延迟,尽管这种异步保存模式,所以看起来应用程序中的所有删除都很慢。

如果,或者,我分配一个新的NSPrivateQueueConcurrencyType上下文,将其持久存储协调器设置为 AppDelegate 中的主 PSC,并执行删除和保存,它仍然做了很多工作,但 UI 永远不会被阻塞(但我不得不担心关于协调上下文,在主要上下文中重新获取)。

任何想法我可能做错了什么,或者你也看到过这种行为吗?

4

1 回答 1

8

删除可能需要很长时间。他们必须修复所有的关系。进行大量删除时,您应该做几件事。

首先,为什么在后台发生删除时您的 UI 会阻塞?因为该后台线程确实忙于执行删除块,并且您的 UI 正在尝试获取以在删除发生时更新数据。

运行实际工作的线程由 FIFO 队列管理,因此如果你给它一个大任务来执行,它将无法执行其他任务,直到长时间运行的任务完成。

您可能正在使用 FRC,它试图在对象和关系发生变化时获取更新。

如果你有一个大的删除,你可能想改变你的 fetch 以便它只在删除发生时查看当前 MOC 的数据。删除完成后,您可以告诉 fetch 请求返回到 store 本身的查询。

此外,当删除大量内容时,最好在一个单独的线程中,在自动释放池中以小块的形式进行。从该后台线程中,一次删除小块,然后使用performBlockAndWait. 这样,您就不会使用删除请求加载工作线程的队列,并且您的 UI 线程可以处理其请求。更快速。

或者,您还可以使用 GCD 的高级功能来拥有一个高优先级和低优先级队列,用于将工作提供给工作线程。您可以将写入放在低优先级队列上,将读取放在高优先级队列上。

于 2012-08-03T20:46:21.953 回答