嵌套的performBlock:在NSManagedObjectContext上

FKD*_*Dev 8 core-data nsmanagedobjectcontext ios

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

[backgroundContext performBlock:^{
   NSFetchRequest *myRequest = ...;  
   __block NSArray *result= nil;
   [backgroundContext performBlockAndWait:^{
       results = [backgroundContext executeFetchRequest:myRequest error:NULL];
   }];
}];
Run Code Online (Sandbox Code Playgroud)

它可能看起来很愚蠢但我有一个现有的代码库,其中包含很多帮助方法来封装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: (...)];
     }];
}
Run Code Online (Sandbox Code Playgroud)

我试过了它,它的工作原理.但我已经学会了(艰难的方式)对核心数据和多线程非常小心.

Jod*_*ins 8

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

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