使用 NSFetchedResultsController 处理后台更改
Posted
技术标签:
【中文标题】使用 NSFetchedResultsController 处理后台更改【英文标题】:Handling background changes with NSFetchedResultsController 【发布时间】:2010-06-07 13:29:13 【问题描述】:我在使用 NSFetchedResultsController 和 CoreData 时遇到了一些烦人的问题,如果能得到帮助,我将不胜感激。
问题 1 - 更新:我在后台线程上更新我的商店,这导致某些行被删除、插入或更新。使用“mergeChangesFromContextDidSaveNotification:”方法将更改合并到主线程上的上下文中。插入和删除会正确更新,但更新不会(例如,单元格标签不会随更改而更新),尽管我已经确认更新来自 contextDidSaveNotifcation,就像插入和删除一样。我目前的解决方法是将上下文的陈旧间隔临时更改为 0,但这似乎不是理想的解决方案。
问题 2 - 删除对象:我的 fetch 批量大小是 20。如果一个对象被前 20 行中的后台线程删除,一切正常。但是如果对象在前 20 行之后并且表格向下滚动,则会引发“CoreData 无法完成错误”错误。我已经尝试重新保存上下文并重新执行 frc 提取 - 都无济于事。注意:在这种情况下,不调用 frc 委托方法“didChangeObject ....”进行删除 - 我认为这是因为当时有问题的对象没有出错(因为它超出了初始提取范围)。但是由于某种原因,上下文仍然认为该对象在附近,尽管它已从存储中删除。
问题 3 - 删除部分:当删除一行导致删除部分时,我得到“部分中的行数无效???”错误。我已经通过从 NSFetchedResultsChangeMove: 部分中删除“reloadSection”行并将其替换为“[tableView insertRowsAtIndexPaths ....”来解决此问题,这似乎可行,但我再次不确定这是否是最佳解决方案。
任何帮助将不胜感激。谢谢!
【问题讨论】:
【参考方案1】:我认为您的所有问题都与获取的结果控制器的缓存有关。
问题 1 是由 FRC 使用缓存的对象(其 ID 未更改)引起的。当您添加或删除更改 ID 的对象并强制更新缓存但更改对象的属性不会可靠地这样做。
问题 2 是由 FRC 检查缓存中的对象引起的。最有可能的是,该对象具有在缓存中持续存在的无故障关系。当您在后台删除它时,FRC 会尝试在关系另一端的对象中出错并且不能。
问题 3:同样的问题。缓存不反映更改。
当 FRC 以外的其他对象正在修改数据模型时,您真的不应该使用 FRC 的缓存。你有两个选择:
-
(首选)不要使用缓存。创建 FRC 时,将缓存属性设置为 nil。
在后台进程更改数据模型时清除缓存。
当然,两个首先破坏了使用缓存的目的。
缓存仅在数据大部分是静态的和/或 FRC 管理更改时才有用。在任何其他情况下,您都不应该使用它,因为 FRC 需要反复检查实际的数据模型,以确保它对数据有当前的理解。它不能依赖它隐藏的对象副本,因为另一个输入可能已经改变了真实的对象。
【讨论】:
非常感谢。事实上,缓存是造成我许多问题的原因。我现在只剩下 1 个问题 - 当我在从后台上下文同步删除后保存上下文时,会调用 frc NSFetchedResultsChangeInsert 并重新插入已删除的联系人,尽管合并策略是 NSRollbackMergePolicy。 未将过时间隔设置为 0 修复了上述评论中描述的问题,但这再次导致更新更改,例如单元格标签名称更改,未反映。 最后一个问题在某种程度上与我为后台 moc 使用单独的持久存储协调器这一事实有关。结合使用主 psc 和不使用缓存解决了所有问题。【参考方案2】:我的建议:
检测后台线程所需的更改
将更改作为有效负载发布到主线程
进行实际更改并保存在主线程上(主线程上的托管对象上下文)
一定要为 FRC 使用缓存;你会得到更好的表现
引用 Michael Privat 和 Robert Warner 的“Pro Core Data for ios”:
“Core Data 智能地管理其缓存,因此如果结果被另一个调用更新,缓存会在受影响时被删除。”
【讨论】:
以上是关于使用 NSFetchedResultsController 处理后台更改的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 3 中难以配置 NSFetchedResultsController