3

我知道这不是一个新话题,但我还没有找到关于我的问题的明确答案。

我正在开发一个项目,该项目有一个包含“书”的核心数据模型。因此,当我通过网络下载 json 数据时,我想将这些 Book 模型存储在我的核心数据中(当然是在后台线程中以不阻塞 UI),然后将这些 Book 模型传递给我的控制器并加载表。

然而,当我学习了 Apple 的 Core Data Reference 之后,我就迷惑了。该文件说我不应该在上下文之间传递托管对象。但是我有两个上下文,一个用于主线程,一个用于后台线程,用于下载、存储数据和获取当前更新的数据。所以我应该做的是在后台获取托管对象ID,并将这些ID传递给主线程中的上下文,然后在主线程中获取具有这些ID的托管对象。

问题来了。在主线程中获取具有 id 的托管对象会阻塞 UI 吗?当我在主线程中获取带有 id 的托管对象时,我是否正在访问 SQLite?如果这些获取的托管对象中有一些是错误的,这意味着如果我想获取它们的属性,我可能会执行 IO,我认为它仍然会阻塞我的 UI。

那么,在不阻塞 UI 的情况下,使用 Core Data 在后台获取数据并在主线程中显示这些数据(UI 操作应该在主线程中)的实用模式是什么?

感谢您的任何帮助!


重新思考:

实际上所有的答案都没有解决我的问题。 但是,我又回到了一个考虑,即当我们需要在核心数据中使用多线程编程时。在大多数情况下,直接使用核心数据可能就足够高效了。我高估了主线程中核心数据操作的成本。

但是,我仍然希望有人推荐一种实用的模式来在后台进行获取,并在主线程中显示。我会很感激的!

4

5 回答 5

3

在你的情况下,我会使用三个 MOC。

NSManagedObjectContext *worker = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyTyep];
worker.persistentStoreCoordinator = // your PSC
NSManagedObjectContext *main = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
main.parentContext = worker;

然后,每当您想要执行背景内容时,创建一个背景 MOC 作为主 MOC 的子对象。

NSManagedObjectContext *background = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
background.parentContext = main;

请记住,保存上下文只会保存一个级别。因此,当您保存背景上下文时,更改将自动推送到主上下文中。

然后,您可以随时保存主上下文......但在某些时候您需要保存工作人员上下文。 UIManagedDocument自动为您处理主要/工作人员保存交互(但您在使用它时放弃了一些控制)。

您在这里获得的另一个好处是实际的 IO 操作不会发生在主线程中。

于 2013-04-23T13:42:36.660 回答
1

这完全取决于您在数据库中插入了多少次。

我发现最好在后台线程中完成所有下载,然后在主线程中插入对象。只要每 30 分钟只有几百次更新,对 UI 性能的影响应该没问题。以我的经验,这样做的健壮性和简单性远远超过了对主线程的小性能影响——你不必关心同步上下文,确保你在正确的线程中使用正确的对象等。

于 2013-04-23T08:42:18.003 回答
1

首先,保持简单,您不希望为了解决您没有的问题而杂耍上下文。是的,主线程上的 fetch 会阻塞 UI,但除非你发现这在真实硬件上是一个真正的问题,否则你可以忽略它。如果您的提取确实如此繁重以至于需要花费大量时间,然后进行分析和优化,那里有很多信息,请查看关于核心数据和仪器的 WWDC '12 视频和优秀的 Marcus Zarra

于 2013-04-23T08:42:45.707 回答
0

您应该在后台线程中执行数据下载,然后在主线程中执行更新/插入操作

于 2013-04-23T08:16:55.197 回答
0

我不知道这是否对您有帮助,但请在精彩的 Cocoa 是我的女朋友博客上尝试此博客条目:Core Data and Threads, without the Headache

它解释了解决这个问题的一些方法,还处理了 UI 和主线程问题。

于 2013-04-23T08:45:48.093 回答