Short Version: Using two managed object contexts, and while the context is saving to the store the application bombs when I attempt to merge the two contexts and reload the table view.
Long Version:
Okay, so my application is set up as thus.
3 view controllers, all table views.
Platforms View Controller - Games View Controller (Predicated upon platform selection) - Add Game View Controller
I ran into a problem when Games View Controller was bombing when adding a new entry to the context, because the fetched results contorller wanted to update the view for something that didn't match the predicate.
As a solution, I rebuilt the Add Controller to use a second NSManagedObject Context, called adding context, following the design pattern in the Core Data Books example.
My Games List View Controller is a delegate for the add controller, to handle all the saving, so my addButtonPressed method looks like this
- (IBAction) addButtonPressed: (id) sender {
AddGameTableViewController *addGameVC = [[AddGameTableViewController alloc] initWithNibName:@"AddGameTableViewController" bundle:nil];
NSManagedObjectContext *aAddingContext = [[NSManagedObjectContext alloc] init];
self.addingContext = aAddingContext;
[aAddingContext release];
[addingContext setPersistentStoreCoordinator:[[gameResultsController managedObjectContext] persistentStoreCoordinator]];
addGameVC.context = addingContext;
addGameVC.delegate = self;
addGameVC.newGame = (Game *)[NSEntityDescription insertNewObjectForEntityForName:@"Game" inManagedObjectContext:addingContext];
UINavigationController *addNavCon = [[UINavigationController alloc] initWithRootViewController:addGameVC];
[self presentModalViewController:addNavCon animated:YES];
[addGameVC release];
[addNavCon release];
}
There is also a delegate method which handles the saving. This all works swimmingly. The issue is getting the table view controller in the GameListViewController to update itself.
Per the example, an observer is added to watch for the second context to be saved, and then to merge the addingContext with the primary one.
So I have:
- (void)addViewController:(AddGameTableViewController *)controller didFinishWithSave:(BOOL)save {
if (save) {
NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter];
[dnc addObserver:self selector:@selector(addControllerContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:addingContext];
//snip! Context Save Code
[dnc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:addingContext];
}
self.addingContext = nil;
[self dismissModalViewControllerAnimated:YES];
}
- (void)addControllerContextDidSave:(NSNotification*)saveNotification
{
NSManagedObjectContext *myContext = [gameResultsController managedObjectContext];
[myContext mergeChangesFromContextDidSaveNotification:saveNotification];
}
So now, what happens is after save is pressed, the application hangs for a moment and then crashes. The save is processed, as the new game is present when I relaunch the application, and the application seems to be flowing as appropriate, but it bombs out for reasons that are beyond my understanding.
NSLog of the saveNotification spits out this:
NSConcreteNotification 0x3b557f0 {name = NSManagingContextDidSaveChangesNotification; object = <NSManagedObjectContext: 0x3b4bb90>; userInfo = {
inserted = {(
<Game: 0x3b4f510> (entity: Game; id: 0x3b614e0 <x-coredata://13168366-B8E7-41C8-B384-BAF14A5E08D9/Game/p2> ; data: {
name = "Final Fantasy XIII";
platform = 0x3b66910 <x-coredata://13168366-B8E7-41C8-B384-BAF14A5E08D9/Platform/p20>;
})
)};
updated = {(
<Platform: 0x3b67650> (entity: Platform; id: 0x3b66910 <x-coredata://13168366-B8E7-41C8-B384-BAF14A5E08D9/Platform/p20> ; data: {
games = (
0x3b614e0 <x-coredata://13168366-B8E7-41C8-B384-BAF14A5E08D9/Game/p2>,
0x603a530 <x-coredata://13168366-B8E7-41C8-B384-BAF14A5E08D9/Game/p1>
);
name = "Xbox 360";
})
)};
}}
I've tried both a simple
[self.tableView reloadData];
and the more complicated multi-method table updating structure in the Core Data Books example. Both produce the same result.