2012-08-03 57 views
5

在我的应用程序中,我有一个“主”NSPrivateQueueConcurrencyType上下文,作为视图控制器依赖和传递的上下文的父级。我想这样做是为了利用异步保存(此应用程序将iCloud与Core Data配合使用,并节省了大量输出无处不在日志的工作)。设置类似于在this article缓慢删除并保存在嵌套NSManagedObjectContext

的底部所提及的Zarra方法在应用程序中保存通常是这样的:

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

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

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

实际上,我刚刚注意到,尽管存在这种异步保存模式,但单个对象的轻扫删除删除操作会导致明显的延迟,因此应用中的所有删除操作都很慢。

如果或者我分配了一个新的NSPrivateQueueConcurrencyType上下文,请将其持久存储协调器设置为AppDelegate中的主PSC并执行删除并保存,但它仍执行大量工作,但UI永远不会被阻止(但那么我不得不担心协调的背景下,在主要情况下重新考虑)。

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

回答

8

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

首先,为什么你的UI在后台删除时发生阻塞?由于该后台线程真的忙于执行删除块,并且您的用户界面正试图在删除正在进行时更新数据。

运行实际工作的线程由一个FIFO队列管理,所以如果给它一个很大的任务来执行,它将不能执行其他任务,直到长时间运行完成。

您可能正在使用FRC,并且它在尝试在对象和关系发生更改时获取更新。

如果你有一个很大的删除,你可能想要改变你的提取,所以它只会查看当前MOC的数据,而删除正在发生。删除完成后,您可以通知提取请求返回查询到商店本身。

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

或者,您还可以使用GCD的高级功能来创建高优先级和低优先级的队列,用于将工作馈送给工作线程。您可以将写入放在低优先级队列上,并在高优先级队列上进行读取。

+0

谢谢Jody!我一直都遇到你有用的答案。我正在做更多的工作来研究我的问题。在一个屏幕上,我展示了我的项目(项目有许多任务),并且不使用NSFRC。我正在研究你为我的另一个屏幕(它列出了任务并使用NSFRC)提到的事情,其中​​使用嵌套方法轻松删除单个任务的速度很慢(如果我恢复到标准,则速度很快NSMainQueueConcurrencyType上下文绑定到PSC) – azsromej 2012-08-04 20:59:08

+0

在仪器中运行它。这是查看到底发生了什么的最好方法。 – 2012-08-04 21:12:14

+0

奇怪的是,使用滑动删除会导致阻止UI的保存,但使用Edit-Done按钮(点击红色圆圈然后删除)不会阻止,尽管流过commitEditingStyle:forRowAtIndexPath(其中deleteObject:并保存:发生) – azsromej 2012-08-05 17:49:06