使用 NSFetchedResultsController 处理背景变化
我在 NSFetchedResultsController 和 CoreData 方面遇到了一些棘手的问题,如果能获得帮助,我将非常感激。
问题 1 - 更新:我在后台线程上更新我的商店,这导致某些行被删除、插入或更新。使用“mergeChangesFromContextDidSaveNotification:”方法将更改合并到主线程上的上下文中。插入和删除已正确更新,但更新却未正确更新(例如,单元格标签未随更改而更新),尽管我已确认更新将通过 contextDidSaveNotifcation 进行,与插入和删除完全相同。我当前的解决方法是暂时将上下文的陈旧间隔更改为 0,但这似乎不是理想的解决方案。
问题 2 - 删除对象:我的获取批量大小是 20。如果后台线程删除了前 20 行中的对象,则一切正常。但是,如果该对象位于前 20 行之后并且表格向下滚动,则会引发“CoreData 无法完成故障”错误。我尝试重新保存上下文并重新执行 frc 获取 - 一切都无济于事。注意:在这种情况下,不会调用 frc 委托方法“didChangeObject....”进行删除 - 我认为这是因为当时没有出现问题的对象(因为它超出了初始获取范围) )。但由于某种原因,上下文仍然认为该对象在附近,尽管该对象已从存储中删除。
问题 3 - 删除节:当删除一行导致删除节时,我得到了“节中行数无效???”错误。我通过从 NSFetchedResultsChangeMove: 部分中删除“reloadSection”行并将其替换为“[tableView insertRowsAtIndexPaths...”来解决此问题,这似乎有效,但我再次不确定这是否是最佳解决方案。
任何帮助将不胜感激。谢谢你!
I am having a few nagging issues with NSFetchedResultsController and CoreData, any of which I would be very grateful to get help on.
Issue 1 - Updates: I update my store on a background thread which results in certain rows being delete, inserted or updated. The changes are merged into the context on the main thread using the "mergeChangesFromContextDidSaveNotification:" method. Inserts and deletes are updated properly, but updates are not (e.g. the cell label is not updated with the change) although I have confirmed the updates to come through the contextDidSaveNotifcation, exactly like the inserts and deleted. My current workaround is to temporarily change the staleness interval of the context to 0, but this does not seem like the ideal solution.
Issue 2 - Deleting objects: My fetch batch size is 20. If an object is deleted by the background thread which is in the first 20 rows, everything works fine. But if the object is after the first 20 rows and the table is scrolled down, a "CoreData could not fulfill a fault" error is raised. I have tried resaving the context and reperforming the frc fetch - all to no avail. Note: In this scenario, the frc delegate method "didChangeObject...." is not called for the delete - I assume this is because the object in question had not been faulted at that time (as it is was outside the initial fetch range). But for some reason, the context still thinks the object is around, although is has been deleted from the store.
Issue 3 - Deleting sections : When the deletion of a row leads to the deletion of a section, I have gotten the "invalid number of rows in section???" error. I have worked around this by removing the "reloadSection" line from the NSFetchedResultsChangeMove: section and replacing it with "[tableView insertRowsAtIndexPaths...." This seems to work, but once again, I am not sure if this is the best solution.
Any help would be greatly appreciated. Thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我的建议:
检测后台线程所需的更改
将更改作为有效负载发布到主线程
进行实际更改并保存在主线程上(主线程上的托管对象上下文)
请使用 FRC 的缓存;您将获得更好的性能
引用 Michael Privat、Robert Warner 的“Pro Core Data for iOS”:
<块引用>
“Core Data 智能地管理其缓存,因此,如果其他调用更新结果,则缓存会在受影响时被删除。”
My advice:
Detect the changes needed on the background thread
Post the changes to the main thread as a payload
Make the actual changes and save on the main thread (Managed Object Context on the main thread)
DO use the cache for the FRC; you'll get better performance
Quote from "Pro Core Data for iOS" by Michael Privat, Robert Warner:
我认为您的所有问题都与获取的结果控制器的缓存有关。
问题 1 是由 FRC 使用缓存对象(其 ID 未更改)引起的。当您添加或删除对象时,会更改 ID 并强制更新缓存,但更改对象的属性不会可靠地执行此操作。
问题 2 是由 FRC 检查缓存中的对象引起的。最有可能的是,该对象具有在缓存中持久存在的无故障关系。当您在后台删除它时,FRC 会尝试在关系另一端的对象中出错,但不能。
问题3:同样的问题。缓存不反映更改。
当 FRC 以外的某个对象正在修改数据模型时,您确实不应该使用 FRC 的缓存。您有两个选择:(
当然,这两个首先就违背了使用缓存的目的。
仅当数据大部分是静态的和/或 FRC 管理更改时,缓存才有用。在任何其他情况下,您都不应该使用它,因为 FRC 需要反复检查实际数据模型以确保它对数据有最新的理解。它不能依赖于它存储的对象副本,因为另一个输入可能已经更改了真实对象。
I think all your problems relate to the fetched results controller's cache.
Issue 1 is caused by the FRC using the cached objects (whose IDs have not changed.) When you add or remove an object that changes the IDs and forces an update of the cache but changing the attributes of an object doesn't do so reliably.
Issue 2 is caused by the FRC checking for the object in cache. Most likely, the object has an unfaulted relationship that persist in the cache. When you delete it in the background the FRC tries to fault in the object at the other end of the relationship and cannot.
Issue 3: Same problem. The cache does not reflect the changes.
You really shouldn't use a FRC's cache when some object other than the FRC is modifying the data model. You have two options:
Of course, two defeats the purpose of using the cache in the first place.
The cache is only useful if the data is largely static and/or the FRC manages the changes. In any other circumstance, you shouldn't use it because FRC need to check the actual data model repeatedly to ensure that it has a current understanding of the data. It can't rely on the object copies it squirreled away because another input may have changed the real objects.