views:

164

answers:

3

I'm developing an iPhone app where I use a NSFetchedResultsController in the main table view controller. I create it like this in the viewDidload of the main table view controller:

NSSortDescriptor *sortDescriptorDate = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES];
 NSSortDescriptor *sortDescriptorTime = [[NSSortDescriptor alloc] initWithKey:@"start" ascending:YES];
 NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptorDate,sortDescriptorTime, nil];
 [fetchRequest setSortDescriptors:sortDescriptors];
 [sortDescriptorDate release];
 [sortDescriptorTime release];
 [sortDescriptors release]; 




 controller = [[NSFetchedResultsController alloc]
      initWithFetchRequest:fetchRequest
      managedObjectContext:context
      sectionNameKeyPath:@"date"
      cacheName:nil];
 [fetchRequest release];

 NSError *error;
 BOOL success = [controller performFetch:&error];

Then, in a subsequent view, I create a new object on the context:

  TestObject *testObject = [NSEntityDescription insertNewObjectForEntityForName:@"TestObject" inManagedObjectContext:context];

The TestObject has several related object which I create in the same way and add to the testObject using the provided add...Objects methods.

Then, if before saving the context, I press cancel and go back to the main table view, nothing is shown as expected. However, if I restart the app, the object I created on the context shows in the main table view. How come? At first, I thought it was because the NSFetchedResultsController was reading from the cache, but as you can see I set this to nil just to test. Also, [context hasChanges] returns true after I restart. What am I missing here?

A: 

Your NSManagedObjectContext instance is getting saved if you see the object when you restart the app.

Your cancel button handler should do an undo or a rollback.

Shaggy Frog
But why the NSManagedObjectContext saved? I don't run [context save] in my code.
Andreas
I don't know, but if the object is in your app between launches then it must be getting saved somehow. Perhaps you're merging contexts or something? (P.S. The `save:` method takes a parameter for the error)
Shaggy Frog
No, I'm just using one context. I'm using the error parameter normally, yes.Just for testing, I've removed all the context saves in my code, and everything is still there after a restart.
Andreas
usually the implementation provided by Xcode of your AppDelegate does save the context in - (void)applicationWillTerminate:(UIApplication *)application
Martin Brugger
I didn't think so either, so can anyone explain what is going on here?
Andreas
We need more info. Try an experiment. If you do an `undo` or a `rollback` in the cancel button hander -- as I've already suggested -- does the problem go away?
Shaggy Frog
Andreas
I wonder if the context is saved automagically at exit? I am searching now but I can't find anything related to that. (P.S. You should do the test on the error object pointer instead: `if (error) { //handle error }`)
Shaggy Frog
+1  A: 

The context is never saved automatically. If you are seeing saves then there is a call to -save: somewhere. QED

To confirm things are being written to disk are you looking at the sqlite file itself? You can peek in there to see what is being written. If there is nothing in there, perhaps you are generate default objects or something on launch.

Marcus S. Zarra
Thanks Marcus, you pointed me in the right direction. When I created the project in Xcode, I chose "use Core Data for storage". Turns out, using that option, the context is saved in applicationWillTerminate.
Andreas
A: 

It sounds to me like your cancel button isn't actually cancelling anything (i.e. not running undo or rollback, as Shaggy Frog states.

As for the context being saved, did you start by creating an Xcode project with the "Use Core Data for storage" box checked? If so, the generated template includes a context save on application exit.

Check in - (void)applicationWillTerminate:(UIApplication *)application in your AppDelegate.

Shaun
Yes, I created the project using "Use Core Data for storage", and I was not aware of the inclusion of context save in applicationWillTerminate.
Andreas