在嵌套的 NSManagedObjectContext 中缓慢删除和保存

Posted

技术标签:

【中文标题】在嵌套的 NSManagedObjectContext 中缓慢删除和保存【英文标题】:Slow deletes and saves in nested NSManagedObjectContext 【发布时间】:2012-08-03 18:40:06 【问题描述】:

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

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

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

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

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

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

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

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

【问题讨论】:

【参考方案1】:

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

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

运行实际工作的线程是由一个先进先出队列管理的,所以如果你给它一个大的任务去执行,它在长时间运行的任务完成之前将无法执行其他任务。

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

如果您有大量删除,您可能需要更改您的提取,以便在删除发生时仅查看当前 MOC 中的数据。删除完成后,您可以告诉 fetch 请求返回到 store 本身的查询。

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

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

【讨论】:

谢谢乔迪!我总是遇到你有用的答案。我正在做更多的工作来调查我的问题。在一个屏幕上,我展示了我的项目(项目有很多任务)并且不使用 NSFRC。我正在研究您在我的另一个屏幕(它确实列出了任务并使用 NSFRC)中提到的事情,其中​​使用嵌套方法滑动删除单个任务很慢(如果我恢复到标准,则速度很快NSMainQueueConcurrencyType 上下文绑定到 PSC) 在仪器中运行它。这是准确了解正在发生的事情的最佳方式。 奇怪,使用 swipe-to-delete 保存会阻止 UI,但使用 Edit-Done 按钮,点击红色圆圈,然后点击 Delete,不会阻止,尽管两者都流过commitEditingStyle:forRowAtIndexPath (其中 deleteObject: 和 save: 发生) 捕获每种情况的大头钉轨迹,您将看到在 commitEditingStyle:forRowAtIndexPath: 之前发生了什么。 删除了一个获取行的调用(在 commitEditingStyle 之后的滑动删除案例中调用)并且主线程停止被阻塞。在另一个我知道我没有获取任何东西的屏幕上查看一些问题,并了解有关 Instruments 的更多信息;感谢您的帮助!

以上是关于在嵌套的 NSManagedObjectContext 中缓慢删除和保存的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Interface Builder 的 XIB 传递 NSManagedObjectContext

MagicalRecord MR_saveToPersistentStoreWithCompletion 极慢

无法将表达式的类型“NSDictionary”转换为类型“StringLiteralConvertible”

ios核心数据 - 将实体记录复制到另一个实体

iOS - 核心数据 - NSManagedObjectContext - 不确定是不是保存

在 BigQuery 中取消嵌套多个嵌套字段