Strange behavior when using child/parent NSManagedObjectContext
core-data, ios5, nsmanagedobjectcontext, objective-c
Solution
My solution was to:
1) Use the background MOC as the parent MOC and the main MOC as a child. As a bonus I don't need to save the main MOC to get the permanent IDs.
[DC.backgroundMOC performBlock:^{
// Add, save and update managed objects
[DC saveContext]; // The changes is being pushed to the main context
}];
2) Use NSManagedObjectContextDidSaveNotification to keep the main MOC up to date (the main MOC is updating the UI)
- (void) backgroundMOCSaved:(NSNotification*)notification {
[mainMOC performBlock:^{
[mainMOC mergeChangesFromContextDidSaveNotification:notification];
}];
}
Problem
I'm developing an application where I need to both calculate things (multiple seconds operations) and write things (sync data with a server) on a background thread. Because of this I use two NSManagedObjectContexts (MOC), a child and a parent, and these must always be in sync. To make sure they are in sync I always edit/add data to the child MOC so it gets pushed to the main MOC with the following pattern: ``` [childMOC performBlock:^{ MyObject *myObject = *create new object in childMOC* [childMOC save:&error]; [mainMOC performBlock:^{ [mainMOC save:&error]; // Is this mandatory to make it work correctly? // [childMOC performBlock:^{ // [childMOC refreshObject:myObject mergeChanges:NO]; // }]; }]; }]; ``` After a while I seemed to have two versions of the same object in the background context, one with a temporary ID and one with a permanent ID. If I e.g. added child objects to the "real" one (by passing fresh permanent ID from main to child MOC) I didn't see these objects when I retrieved my object in the background MOC cause it is the old temporary one that is cached. I've seen the pattern above been used a lot, but it seems strange that no one mentioned this temporary/permanent ID problem. It doesn't feel right that it can be two versions of the same object within a context. If I pass an NSManagedObjectID to the child MOC and retrieve that, shouldn't the child MOC update my existing object instead of creating a new one and leave my old temporary as cached default? Do I need to use the commented row on each place I create an object? Or maybe it works with mergeChangesFromContextDidSaveNotification, will that give the same effect?