缓慢删除并保存嵌套的NSManagedObjectContext

azs*_*mej 5 core-data nsmanagedobjectcontext ios

在我的应用程序中,我有一个"主" NSPrivateQueueConcurrencyType上下文,它充当NSMainQueueConcurrencyType视图控制器依赖和传递的上下文的父级.我想这样做是为了利用异步保存(这个应用程序使用iCloud与核心数据,并节省了很多工作导出无处不在的日志).该设置类似于本文底部提到的Zarra方法

在应用程序中保存通常如下所示:

[context save:nil];
[context.parentContext performBlock:^{
     [context.parentContext save:nil];
}];
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

我可能做错了什么想法,或者你也见过这种行为?

Jod*_*ins 8

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

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

运行实际工作的线程由FIFO队列管理,因此如果您为其执行大任务,则在长时间运行完成之前,它将无法执行其他任务.

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

如果您有一个大的删除,您可能想要更改您的提取,以便它只在删除发生时查看数据的当前MOC.删除完成后,您可以告诉获取请求返回查询到存储本身.

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

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