CoreData: How to revert a managed object to its original state

In my iPhone application I am using Apple’s database technology CoreData with TableViewControllers in a Master-Detail relationship. I am using Apple’s preferred way for iOS applications to set the managed object context and the managed object which is edited in the detail view as class members of my Detail Viewcontroller.

DatabaseThe fields of the managed object are displayed and edited in table cells. The viewcontroller displays two UIBarButtons named “Save” and “Cancel”. The save action is no problem as all values are stored as soon as the UITextField’s delegate method

- (void)textFieldDidEndEditing:(UITextField *)textField

is executed.

The cancel action was much more of a challenge. Many solutions propose to use

  1. a second managed object context which is discarded when cancel is touched or
  2. the NSUndoManager

Both are valid, but in my iPhone app where a single managed object is edited in one table view and all changed values in this single object should be reverted to the last committed values. Therefore is seems to me to be a much more light-weight approach to just overwrite all changed values with the respective values when the object was last committed.
The NSManagedObject class has two interesting properties to achieve this behaviour:

  1. changedValues and
  2. committedValuesForKeys

Having these two methods, it is quite easy to revert an object to its last commited state. I developed a Category for NSManagedObject

to have this feature which is absolutely convenient for 90% of all my requirements in my iPhone application.

Here is the code for NSManagedObject+RevertChanges.h:

#import <foundation/Foundation.h>
#import <coredata/CoreData.h>
 
@interface NSManagedObject (NSManagedObject_RevertChanges)
 
- (void) revertChanges;
 
@end

And this is the code for NSManagedObject+RevertChanges.m :

#import "NSManagedObject+RevertChanges.h"
 
@implementation NSManagedObject (NSManagedObject_RevertChanges)
 
- (void) revertChanges {
    // Revert to original Values
    NSDictionary *changedValues = [self changedValues];
    NSDictionary *committedValues = [self committedValuesForKeys:[changedValues allKeys]];
    NSEnumerator *enumerator;
    id key;
    enumerator = [changedValues keyEnumerator];
 
    while ((key = [enumerator nextObject])) {
        NSLog(@"Reverting field ""%@"" from ""%@"" to ""%@""", key, [changedValues objectForKey:key], [committedValues objectForKey:key]);
        [self setValue:[committedValues objectForKey:key] forKey:key];
    }
}
 
@end

You just have to import the header file in your ViewController class with

#import "NSManagedObject+RevertChanges.h"

and you have the method at your fingertips.

Please, feel free to use the code, but any comment is welcome on this approach.