8

当使用NSPrivateQueueConcurrencyTypeNSMainQueueConcurrencyType类型时NSManagedObjectContext,在同一个上下文中进行嵌套的 performBlock 调用是否安全?

[backgroundContext performBlock:^{
   NSFetchRequest *myRequest = ...;  
   __block NSArray *result= nil;
   [backgroundContext performBlockAndWait:^{
       results = [backgroundContext executeFetchRequest:myRequest error:NULL];
   }];
}];

这可能看起来很愚蠢,但我有一个现有的代码库,其中包含许多封装executeFetchRequest调用的辅助方法。我不想假设调用者是否已经使用了 performBlock。例如:

-(void)updateObjects:(BOOL)synchronous
{
    if (YES == synchronous)
        [self fetchHelper];
    else
    {
        [backgroundContext performBlock:^{
             [self fetchHelper];
        }];
    }
}

-(NSArray*)fetchHelper
{
     [self.backgroundContext performBlockAndWait:^{
         //Fetch the objects...
         [self.backgroundContext executeFetchRequest: (...)];
     }];
}

我已经尝试过了,它有效。但我已经学会了(艰难的方式)对 Core Data 和多线程非常小心。

4

1 回答 1

9

是的, performBlockAndWait 是可重入的。直接来自 Apple 的发行说明...

Core Data 使用新选项将 NSManagedObjectContext 类的并发模型形式化。创建上下文时,您可以指定与它一起使用的并发模式:线程限制、私有调度队列或主调度队列。NSConfinementConcurrencyType 选项提供的行为与 5.0 之前的 iOS 版本中存在的行为相同,并且是默认行为。将消息发送到使用队列关联创建的上下文时,如果您的代码尚未在该队列上(对于主队列类型)或在 performBlock... 调用的范围内执行,则必须使用 performBlock: 或 performBlockAndWait: 方法(对于私有队列类型)。在传递给这些方法的块中,您可以自由地使用 NSManagedObjectContext 的方法。performBlockAndWait:方法支持 API 重入。performBlock: 方法包括一个自动释放池,并在完成时调用 processPendingChanges 方法。

于 2012-05-08T15:20:18.710 回答