如何使用 Core Data 有效地保存 UI/主线程中所做的更改?

Posted

技术标签:

【中文标题】如何使用 Core Data 有效地保存 UI/主线程中所做的更改?【英文标题】:How to efficiently save changes made in UI/main thread with Core Data? 【发布时间】:2010-04-09 16:27:21 【问题描述】:

因此,这里有几篇关于将数据从外部数据源导入和保存到 Core Data 的帖子。苹果为此记录了一个合理的模式:“在后台线程上导入和保存,将保存的对象合并到主线程。”一切都很好。

我有一个相关但不同的问题:用户正在修改 UI 和主线程中的数据,因此修改了托管对象上下文 (MOC) 中某些对象的状态。我想不时保存这些更改。有什么好的方法吗?

现在,您可以说我也可以这样做:使用自己的 MOC 创建一个后台线程,并将更改后的 objectID-s 传递到那里。对我来说,catch-22 是对象的 ID 在保存时会发生变化,我不能保证事情发生的顺序。我可能最终将不同的 objectID 传递给同一对象的后台线程,这取决于该对象之前是否已保存,我不知道 Core Data 是否可以解决这个问题并看到不同的 objectID-s 指向到同一个对象,而不是为我创建重复项。 (我可以测试一下,但我先懒得回答这个问题。)

我有一个想法:我总是可以在后台线程上进行 MOC 保存,并将它们与 operationqueue 一起排队,这样总是只有一个保存在进行中。我不会创建新的 MOC,我只会使用与主线程中相同的 MOC。现在,这不是线程安全的,当有人在主线程中修改 MOC 而将其保存在后台线程中时,结果可能是灾难性的。但是,减去线程安全,你可以看到我想要什么样的解决方案。

需要明确的是,我需要解决的问题是,如果我只是在主线程中进行保存,它会在不可接受的时间内阻塞 UI,我想将保存移至后台线程。

所以,问题:

    保存期间对象 ID 发生变化的原因是什么,Core Data 能够将它们解析为同一个对象?这是解决这个问题的正确方法吗? 还有其他好的方法吗?

【问题讨论】:

我认为对象的 ID 在保存过程中不会发生变化。这对我来说根本不合适。 一个对象在第一次保存前有一个ID,保存后有另一个永久ID,保持不变。阅读 CD 文档。 【参考方案1】:

简单地说,您不能将保存移动到后台线程。更改与NSManagedObjectContext 相关,因此对另一个线程上的NSManagedObjectContext 是不可见的。

我建议你分析一下你的存档,看看为什么要花这么长时间。也许让它们更频繁地使用,或者找出可能导致性能问题的其他原因。

您使用的是 SQLite 存储对吗?

更新

如果您使用的是二进制,那肯定会成为一个问题,我相信我之前曾向您提到过。二进制文件必须 100% 加载到内存中,因此也必须 100% 写入磁盘。

【讨论】:

由于另一个线程中讨论的原因,我仍在使用二进制存储(整个存储在内存中的高效运行时处理)。这可能是回到 SQLite 商店的充分理由。二进制存储保存性能似乎会根据信息的变化量呈线性下降。【参考方案2】:

它可能无法解决您的所有问题,但有一种方法-[NSManagedObjectContext obtainPermanentIDsForObjects:error:],您可以使用该方法在将托管对象保存到存储之前获取它的永久 ID。因此,这对您最终进行的任何同步都会有所帮助。

【讨论】:

这无关紧要,因为未保存的更改在创建/加载对象的上下文中是本地的。

以上是关于如何使用 Core Data 有效地保存 UI/主线程中所做的更改?的主要内容,如果未能解决你的问题,请参考以下文章

Core Data,我如何有效地查找和删除托管对象

Core Data 持久化存储异步保存

iOS Core Data Fetch Request,如何使用

既然 objectID 在临时对象和永久对象之间发生变化,如何有效地处理 Core Data 中的临时对象?

如何更新 UI 以显示 Core Data 长时间运行的进程?

Core Data 后台处理,保存不推送到主上下文