在同一个上下文中进行嵌套的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 formalizes the concurrency model for the NSManagedObjectContext class with new options. When you create a context,you can specify the concurrency pattern to use with it: thread confinement,a private dispatch queue,or the main dispatch queue. The NSConfinementConcurrencyType option provides the same behavior that was present on versions of iOS prior to 5.0 and is the default. When sending messages to a context created with a queue association,you must use the performBlock: or performBlockAndWait: method if your code is not already executing on that queue (for the main queue type) or within the scope of a performBlock… invocation (for the private queue type). Within the blocks passed to those methods,you can use the methods of NSManagedObjectContext freely. The performBlockAndWait: method supports API reentrancy. The performBlock: method includes an autorelease pool and calls the processPendingChanges method upon completion.