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;
Right-click on your project's folder in the project navigator and then New File… In the new window, type “data” in the top right corner, select Data Model, and press Next. Give it a name, and save it. Now, let's add all the necessary code to connect Core Data with our project.
An object space to manipulate and track changes to managed objects.
A description of search criteria used to retrieve data from a persistent store.
Look http://www.section42.de/coredata-how-to-revert-a-managed-object-to-its-original-state. This will help you for sure.
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
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With