Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested performBlock: on NSManagedObjectContext

When using NSPrivateQueueConcurrencyType and NSMainQueueConcurrencyType types for NSManagedObjectContext, is it safe to make nested performBlock calls on the same context ?

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

It may seem stupid but I have an existing codebase with a lot of helpers methods which encapsulate the executeFetchRequest calls. I don't want to make assumptions about whether the caller has already used performBlock or not. For example:

-(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: (...)];
     }];
}

I have tried it and it works. But I have learned (the hard way) to be very careful with Core Data and multi-threading.

like image 620
FKDev Avatar asked May 04 '12 08:05

FKDev


1 Answers

Yes, performBlockAndWait is reentrant. Directly from Apple's release notes...

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.

like image 162
Jody Hagins Avatar answered Nov 11 '22 20:11

Jody Hagins