Core Data的NSPrivateQueueConcurrencyType和线程之间共享对象

sam*_*tte 36 iphone concurrency core-data ios5

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

Core Data的一个经验法则是您无法在线程/队列之间共享托管对象.它仍然是这样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
    });
}];
Run Code Online (Sandbox Code Playgroud)

因为我在bg队列和主队列之间共享我的结果数组/对象,所以还是不可接受的?我是否仍需要使用托管对象ID来执行此操作?

Dan*_*ert 66

当您使用时,NSPrivateQueueConcurrencyType您需要执行任何触及该上下文的任何内容-performBlock:方法中属于该上下文的任何对象.

您上面的代码是非法的,因为您将这些对象传递回主队列.但是,新的API可以帮助您解决这个问题:您创建一个与主队列关联的上下文,即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'.
        }];
    }
}];
Run Code Online (Sandbox Code Playgroud)

如果将内部[mainMOC performBlock:]调用移动到自己的方法中,则会减少混淆.您可能还希望将对象ID数组传递回主线程的上下文,而不是为每个对象ID执行一个块.这取决于您的需求.

  • MO属于上下文.它们不是*线程安全的,因此只能在它们所属的上下文队列中触及.从文档中可以清楚地看出,但这就是它试图说的.我从Core Data团队获得了这些信息. (14认同)
  • 在上面的代码示例中,backgroundMOC应该是mainMOC的父级吗?即`[mainMOC setParentContext:backgroundMOC];` (6认同)