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.