核心数据和多线程编程

时间:2013-04-23 07:54:56

标签: iphone ios multithreading core-data thread-safety

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

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

但是,当我学习了Apple的核心数据参考时,我感到困惑。该文档说我不应该在上下文之间传递托管对象。但我有两个上下文,一个用于主线程,一个用于后台线程,用于下载,存储数据和获取当前更新的数据。所以我应该做的是在后台获取托管对象id,并将这些id传递给主线程中的上下文,然后在主线程中使用这些ID获取托管对象。

这就是问题所在。会在主线程块UI中获取带有id的托管对象吗?当我在主线程中获取带有id的托管对象时,我是否正在访问SQLite?如果这些获取的托管对象中的一些是错误的,这意味着如果我想获得他们的属性我可以做IO,我认为它仍然会阻止我的UI。

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

感谢您的帮助!


反思:

实际上所有答案都没有解决我的问题。 但是,当我们需要在核心数据中使用多线程编程时,我回过头来考虑。对于大多数情况,也许它足够有效,可以直接使用核心数据。我高估了主线程中核心数据操作的成本。

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

5 个答案:

答案 0 :(得分: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操作不会发生在主线程中。

答案 1 :(得分:1)

这完全取决于您在数据库中执行的插入量。

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

答案 2 :(得分:1)

首先,保持简单,你不需要玩杂耍上下文来修复你没有的问题。是的,在主线程上获取将阻止UI,但除非您发现这是真实硬件上的真正问题,否则您可以忽略它。如果您的获取确实非常繁重,需要花费大量时间,然后进行配置和优化,那么有很多信息,请查看WWDC '12关于核心数据和仪器的视频以及优秀的Marcus Zarra book

答案 3 :(得分:0)

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

答案 4 :(得分:0)

我不知道这是否会对你有所帮助,但是在精彩的可可是这个博客条目是我的女朋友博客试试:Core Data and Threads, Without the Headache

它解释了解决此问题的一些方法,并且还处理了UI和主要线程问题。