Search code examples
iphoneobjective-ciosipadcore-data

CoreData save/revert unsaved changes


I have a list of objects in a UITableView, managed by a NSFetchedResultsController. When the user selects an object, an edit view is displayed, allowing the user to edit the selected NSManagedObject instance. The properties of the object are updated in the object as the user makes changes.

The thing is, there is, as usual, a Save button and a Cancel button. If the user taps save, the NSManagedObjectContext is saved, and the change is reflected. However, if the user taps cancel, I need the object to revert to the state it was in before. Calling [managedObjectContext rollback] doesn't work for this purpose.

Does anyone know how to properly implement this? I can not store the object's properties as temporary separate ivars during editing, because there are multiple objects that could be edited, all of which have different properties.

Update

What I'm currently doing is storing the NSManagedObject in an instance variable, and calling save: to save and rollback to cancel. Instance variables are modified using either object.property = something or [object setValue:something forKey:@"property"]. This does not work as expected, instead producing this behaviour:

  1. If you edit and save, changes update as expected. However, if you edit again, and cancel without making changes, the state of the object reverts back as it was before the save.

  2. If you edit and cancel, the changes are still updated, as if saved. Editing and cancelling again (without making changes) will revert it back to the state it was in before.

Also:

Could this have anything to do with the way I initialise the NSFetchedResultsController that is used to populate the table view? Code:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSString *entityName = self.entityName;
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:self.context];
[fetchRequest setEntity:entity];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

[fetchRequest setIncludesPendingChanges:NO];

NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:@"Root"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;

Solution

  • Having given up on all the mechanisms in place in CoreData to do this (none of them worked), I ended up storing all the properties of the object as separate variables in the edit view controller, and rolling back to them on cancel.