2013-04-23 177 views
3

我知道这不是一个新话题,但我还没有找到明确的答案在我的问题。核心数据和多线程编程

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

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

问题来了。在主线程块UI中使用id获取托管对象?当我在主线程中使用它们的id来获取托管对象时,我是否正在访问SQLite?如果这些提取的托管对象中有些是错误的,这意味着如果我想获得它们的属性,我可能会执行IO操作,但我认为它仍然会阻止我的UI。

那么,什么是使用核心数据获取的后台数据,也不会妨碍用户界面显示在主线程(UI操作应该在主线程),这些数据的实际模式?

谢谢你的帮助!


反思:

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

但是,我仍然希望有人推荐一种实用的模式在后台执行获取操作,并在主线程中显示。我将不胜感激!

回答

1

这一切都取决于你有多少做插入到你的数据库中执行您的更新/插入操作。

,我发现它的工作最好做所有的下载在后台线程,然后在主线程插入的对象。只要每30分钟只有几百次更新,您就可以对UI性能产生影响。根据我的经验,这样做的稳健性和简单性远远超过对主线程的小性能影响 - 您不必关心同步上下文,确保在正确的线程中使用正确的对象等。

+0

我认为这很有帮助。就我而言,当用户拉动加载更多时,我将下载50本书并插入核心数据,并在我的用户界面中显示所有书籍。我认为核心数据50项只是少量的数据。但是,我正在考虑在用户第一次启动应用程序时是否下载所有图书,只是在主线程中执行所有这些操作可能会非常繁重。 – 2013-04-23 09:02:37

0

您应该执行你的数据在你的后台线程下载,然后在你的主线程

+1

这个答案几乎没有帮助OP。你能提供一些更多的信息。 – Anupdas 2013-04-23 08:26:12

+0

所以当我更新并插入我的主线程时,我可能会阻止我的UI。此外,我所担心的实际上是在主线程中进行提取。如果我在主线程中提取,它会阻塞UI。但是,如果我在后台获取并将ID传递给主线程,然后在主线程中使用这些ID获取托管对象,我是否仍会阻止我的UI? – 2013-04-23 08:35:42

1

首先,保持简单,你不想为了解决你没有的问题而玩耍上下文。是的,在主线程上获取会阻止用户界面,但除非您发现这是真实硬件上的真正问题,否则您可以忽略它。如果您的抓取确实很重,需要花费大量时间,然后进行配置和优化,那么有很多信息,请参阅WWDC在Core Data和Instruments上的12个视频以及优秀的Marcus Zarra book

0

我不知道这是否会帮助你,但给的精彩可可这篇博客在被我的女友博客一试:Core Data and Threads, Without the Headache

它解释了一些对这个问题,还与UI交易和主线问题。

+1

虽然他们说,它只能用于启动ios6,但它提供了一些很好的设计,虽然它是旧的,并且大部分内容都是在iOS5中实现的,但是新的子/父MOC模型已经实现了:) – 2013-04-23 09:06:17

+0

这个答案可能有一直是一个评论,它会一样有用。它没有自己的内容。 – cHao 2013-12-24 18:02:47

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操作不会在主线程中发生。

+0

感谢您的回答。我的答案有两个问题。 首先,我应该使用哪个上下文执行读取操作,然后如何显示结果。第二,“worker”上下文的作用是什么。 @Jody – 2013-04-24 03:05:03

+0

将你的'NSFetchedResultsController'连接到主MOC--它运行在主线程上,这是你想要你的UI的东西。后台上下文是您将用于添加从网络下载的项目的内容。工作者上下文使得实际的IO操作在后台线程中完成,而不是在主线程上完成。 – 2013-04-24 03:55:27