Reputation: 9168
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.
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:
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.
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.
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;
Upvotes: 7
Views: 6866
Reputation: 53
I had the same problem. It happened because the textField
was in modification process when user click back. If user click done on keyboard before click back then everything works fine.
Upvotes: 1
Reputation: 381
Look http://www.section42.de/coredata-how-to-revert-a-managed-object-to-its-original-state. This will help you for sure.
Upvotes: 5
Reputation: 789
You need to make sure you're setting an NSUndoManager
instance on your managed object context as it is nil by default on iOS. Related solution here:
https://stackoverflow.com/a/2214982/318456
Upvotes: 3
Reputation: 9168
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.
Upvotes: 2
Reputation: 10129
I would store the NSManagedObject as a property of the edit view controller. Then you can edit all of its properties, and either save or rollback when dismissing the view.
Upvotes: 0