Core Data lockup with parent/child contexts on iOS 5.1

I ran into an interesting Core Data lockup problem recently. It only arises on iOS 5.1.

I have a master-detail setup, and the master tableview has 3 different sorting schemes. I wrote a method for each of these schemes to create an NSFetchedResultsController, initialize it with proper sort descriptors, give it a cache name, and perform the initial fetch.

When the tableview appears, I fire off the appropriate method to get the NSFetchedResultsController I’ll use immediately. But then I wanted to warm up the caches for the other two modes, in a background GCD queue. Here’s what it looked like:

– (void)warmUpCachesExcepting:(NSInteger)dataviewMode

{

    dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc]

                                    initWithConcurrencyType:NSPrivateQueueConcurrencyType];

        childContext.parentContext = self.staticdataMOC;

        if (dataviewMode != tailNumberDataviewMode) {

            @autoreleasepool {

                [[self class] tailNumberFetchedResultsControllerForContext:childContext

                                                                  delegate:nil];

            };

        }

        if (dataviewMode != ownerDataviewMode) {

            @autoreleasepool {

                [[self class] registrantFetchedResultsControllerForContext:childContext

                                                                  delegate:nil];

            };

        }

        if (dataviewMode != manufacturerDataviewMode) {

            @autoreleasepool {

                [[self class] makeAndModelFetchedResultsControllerForContext:childContext

                                                                    delegate:nil];

            };

        }

        [childContext release];

    });

}

Create a new managed object context, set its parent to my original MOC, go to work on the child. This code worked fine on iOS 6. When I switch sorting orders, the change is snappy. 

When I tested this code on an original iPad running iOS 5.1, the app would hang. I did some digging on Stack Overflow and other places, and saw comments suggesting that parent/child contexts had some problems on 5.1

As it turns out, I don’t need to pass results back to the parent MOC. I just wanted a separate context for my background thread. I changed the setup to create the new MOC and then point its persistent store coordinator back to the original MOC’s PSC.

                       NSManagedObjectContext *workingContext = [[NSManagedObjectContext alloc]

                                                      initWithConcurrencyType:NSPrivateQueueConcurrencyType];

                       workingContext.persistentStoreCoordinator = self.staticdataMOC.persistentStoreCoordinator;


Works like a charm now. I didn’t dig deep enough to see exactly where and why I was hanging.