Coredata 获取不返回刚刚写入存储的结果

Posted

技术标签:

【中文标题】Coredata 获取不返回刚刚写入存储的结果【英文标题】:Coredata fetch not returning result just written to store 【发布时间】:2013-10-15 11:29:30 【问题描述】:

场景:

我在 ios 上使用配置为针对 SQLite 数据库操作的 Magical 记录。默认情况下,MR 配置 coredata 将所有写回主线程上的父上下文序列化。

我使用的模式是,当我不在主线程上时,我使用诸如 MagicalRecord:MR_saveWithBlockAndWait 之类的东西为 coredata 操作创建一个单独的 NSManagedObjectContext。神奇的记录创建上下文,将其连接到父上下文,执行您在回调块中指定的任何操作并最终保存。重要的是,保存应该在操作完成之前提交。

当我完成后台线程的工作时,我通常会通知 UI 发生了一些事情;例如:某些内容已下载/上传/更改。

然后,在 UI 线程上,我使用主线程上的默认上下文创建一个新的 fetch 请求。问题是偶尔 coredata 找不到我之前提交的新对象。问题体现在微妙的竞争条件下,如果 UI 线程由于动画或其他一切正常运行而稍微慢一些 - 但有时它找不到新对象。

从我读过的内容来看,获取请求总是应该进入磁盘。 MOC 上还有一个过时属性,但听起来这仅与缓存有关,如果您执行 fetch 请求,则会被绕过。

有没有人遇到过类似的问题并有什么见解?谢谢。

【问题讨论】:

【参考方案1】:

当然。如果您在后台托管对象上下文中保存更改,但您的 UI 上下文已经加载了该对象,则 UI 上下文可能只是从其缓存而不是存储文件中为您提供数据。

使用多个上下文的常用方法是:

    观察NSManagedObjectContextDidSaveNotification,以便知道后台上下文何时保存更改。

    在此通知的处理程序中,在 UI 上下文中调用 mergeChangesFromContextDidSaveNotification:,以便它使用来自其他上下文的更改来更新自身。

您可能希望在您的 UI 上下文中设置 mergePolicy,因为默认设置是在有任何冲突更改时放弃。

这适用于任何多上下文场景,其中每个上下文都需要使用不同上下文保存的更改进行更新。

【讨论】:

当然,我认为如果我告诉核心数据保存并希望在写入刷新时发出警报,那将是有意义的。但是,我对 MR 代码的阅读是,当您调用 MR_savewithBlockAndWait... 它实际上会等到写入完成。 你没有抓住重点。是否需要合并更改与保存是否完成完全无关。它与使用缓存数据的托管对象上下文有关,您需要告诉它其中一些数据已更改。 没有办法告诉 coredata 从 Sqlite 读取并绕过它的缓存?问题是这样的:因为 coredata 对象被插入/更新/删除并不能告诉你 what 用户的意图。这就是为什么我们有更高级别的消息传递。听起来我需要在 UI 线程上放置一条消息,上面写着“下一次合并更改是因为用户更改了图像颜色”,然后等待合并通知。这似乎是竞争条件的成熟。 还有refreshObject:mergeChanges: 方法。为您要刷新的每个对象调用它,将NO 作为第二个参数,然后重新获取该对象。这通常需要更多的工作,但这是可能的。

以上是关于Coredata 获取不返回刚刚写入存储的结果的主要内容,如果未能解决你的问题,请参考以下文章

只有一个值被写入核心数据。为啥 ?

静态库中的 CoreData 自动迁移

CoreData NSFetchRequest 返回结果,但对象的节数返回 0

存储过程不返回结果,但查询返回

如何在 segue 中从 CoreData 获取结果

CoreData:按创建的顺序获取和排序结果,不使用时间戳