核心数据的NSPrivateQueueConcurrencyType和线程之间的共享对象

iOS 5引入了一种新方法,通过使用NSPrivateQueueConcurrencyType初始化MOC,然后在performBlock:执行获取,在后台线程上快速获取数据performBlock:

核心数据的经验之一就是你不能在线程/队列之间共享pipe理对象。 执行块是否仍然如此performBlock: ? 是以下几点:

 [context performBlock:^{ // fetch request code NSArray *results = [context executeFetchRequest:request error:nil]; dispatch_async(dispatch_get_main_queue(), ^(void) { Class *firstObject = [results objectAtIndex:0]; // do something with firstObject }); }]; 

仍然无法接受,因为我在bg队列和主队列之间共享我的结果数组/对象? 我仍然需要使用托pipe对象ID来做到这一点?

当您使用NSPrivateQueueConcurrencyType您需要在-performBlock:方法内执行任何涉及该上下文属于该上下文的任何对象。

你上面的代码是非法的,因为你将这些对象传递回主队列。 新的API可以帮助你解决这个问题,但是:你创build一个与主队列相关联的上下文,即NSMainQueueConcurrencyType

 // Assume we have these two context (They need to be set up. Assume they are.) NSManagedObjectContext *mainMOC = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType] autorelease]; NSManagedObjectContext *backgroundMOC = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType] autorelease]; // Now this can safely be called from ANY thread: [backgroundMOC performBlock:^{ NSArray *results = [backgroundMOC executeFetchRequest:request error:nil]; for (NSManagedObject *mo in results) { NSManagedObjectID *moid = [mo objectID]; [mainMOC performBlock:^{ NSManagedObject *mainMO = [mainMOC objectWithID:moid]; // Do stuff with 'mainMO'. Be careful NOT to use 'mo'. }]; } }]; 

如果您将内部[mainMOC performBlock:]调用移动到其自己的方法中,则会变得不那么令人困惑。 您可能还想将对象ID数组传递回主线程的上下文,而不是为每个对象ID执行一个块。 这取决于你的需求。

正如Daniel Eggert解释的那样,情况绝对如此。 NSMainQueueConcurrencyType是一个例外,你也可以在主线程(也可以通过performBlock机制从其他线程)安全地使用托pipe对象上下文和对象。 这个用处不可低估!

iOS 5还引入了父上下文的概念,这也大大简化了后台操作,消除了使用通知来传播线程间变化的需要。

WWDC 2012video“Session 214 – 核心数据最佳实践”对这两个主题进行了更详细的介绍,内容非常全面。 video对于使用核心数据的人来说是必不可less的。