I am using two managed object contexts in my iOS app. The first context is the parent of the second, utilizing the new nested managed contexts model introduced in iOS 5. Both of these contexts were created with the NSMainQueueConcurrencyType.
What I am trying to achieve is a nice way to handle temporary additions and edits to my data that may or may not get saved and have a logical distinction where the main controller object owns the first context (parent) and the sub-controller owns the 2nd context (child). Changes are thusly bubbled up and the main controller can decide whether or not to save its context. The fact that my contexts are nested requires that they be setup not using the confinement pattern (NSConfinementConcurrencyType).
My question is: is this pattern I’m trying to implement flawed? I just read from multiple posts that using multiple contexts on the main thread is probably not the best idea most of the time. I’m also struggling to determine where I should be using performBlockAndWait: on my contexts. Should I use it every time a message is sent to a context, even if I’m sure I’m currently executing in the main thread? Does this include spots where I am creating a new NSManagedObject like so:
[theManagedObjectContext performBlockAndWait:^
{
id *myObj = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity" inManagedObjectContext:theManagedObjectContext];
// more stuff done here
}];
What about spots where I make changes to my NSManagedObjects? Do I need to wrap those in a performBlockAndWait: as well? What about spots where I use an NSFetchedResultsController and send it the performFetch message?
Am I better off just using one context and figuring out how the undo manager works?
The documentation for these new Core Data features is very sparse from what I’ve seen…
My understanding is that you should always use the block methods,
-performBlock:and-performBlockAndWait:when sending messages to an NSManagedObjectContext that was not initialized using the confinement pattern. Obviously which method you use will depend on your needs.As far as initializing both parent and child with the
NSMainQueueConcurrencyType, this is only necessary if the child context is connected to the UI. If not, creating this child context to offload some non-essential work would be best suited on a private thread using theNSPrivateQueueConcurrencyType. You’re already using the block based methods, so the changes necessary should be minimal.