NSUndoManager with Core Data Objects

I am very new to using NSUndoManager, that too with core data objects.

I found not too difficult, but it works in a different way when compared to the way i thought before.

Here's my Imagination about NSUndoManager before using it:

Once an object for "NSUndoManager" is created and assigned to any "NSManagedObjectContext"(MOC), just calling the "undo" method of "NSUndoManager" would undo all the changes made in the MOC.


My imagination about "NSUndoManager" is dead simple right ?
Of course, i know there are several features that we'll be missing if it works in that way, like you cant undo a specific operation and redo the same way.


After learning step by step, got to know that these are all the few simple steps to use the "NSUndoManager" :

(i) Create an instance for "NSUndoManager", like this or as you wish with "alloc/init" and set that object to your MOC object :

        [self.managedObjectContext setUndoManager:[NSUndoManager new]];

(ii) For any changes that you wish to undo/redo later, you need to tell the "NSUndoManager" that these are all the changes that you'll need later on to go back/forward-undo/redo. So, informing it to keep this in the list.

So, to know the "NSUndoManager" about the changes that you want to track, you need to call "beginUndoGrouping" & "endUndoGrouping".

For example, if you are gonna change some properties of a "NSManagedObject"present in the MOC, then you can tell the "NSUndoManager" like this :

    [[[self managedObjectContext] undoManager] beginUndoGrouping];
    self.person.name = @"Saravanan";
    [[[self managedObjectContextundoManagerendUndoGrouping];

Now, the "NSUndoManager" holds the changes made in the self.person object.

If you want to track a particular change, you can do so like this :
    [[[self managedObjectContextundoManagerbeginUndoGrouping];
    [[[self managedObjectContextundoManagersetActionName:@"nameChanges"];
    self.person.price = @"Saravanan";
    [[[self managedObjectContextundoManagerendUndoGrouping];

This is just like tagging a single change for us to identify it later.

So, above are the ways that you can use to tell the "NSUndoManager" about the changes to track them.
You can have any number of changes been tracked and if you want to limit that, then you can use "setLevelsOfUndo" method and you can set the number of levels of undo you want to have.

Undo/Redo Operation :

For undoing any changes made to the MOC, you can use "undo" method of "NSUndoManager" just like this :
    [self.managedObjectContext undo];

and for sure you need to save this change to your MOC. 
So, here is the perfect undo process :
    [self.managedObjectContext undo];
    [self.managedObjectContext save:nil];

The above code undos the latest changes to MOC, but what if you want to undo a particular change ?
Remember that we've set an "ActionName" (nameChanges). We need to tell the "NSUndoManager" to pick that particular change for us. 
You can do that like this : 
    [self.modifiersMOC.undoManager undoActionName]

The above line returns the action name that you've set for the changes to MOC and nil if you have set nothing.

Also, "NSUndoManager" provides an API to let you check whether there are any changes that you can undo/redo like this :
    [self.modifiersMOC.undoManager canUndo]
    [self.modifiersMOC.undoManager canRedo]

The above API's returns a BOOL value that tells whether there are any changes to undo/redo or not.

And what if you want to undo all the changes tracked by "NSUndoManager".
You can do so like this :

    while ([self.modifiersMOC.undoManager canUndo]) {
         [self.managedObjectContext undo];
         [self.managedObjectContext save:nil];
    }

The same is for Redo :

    while ([self.modifiersMOC.undoManager canRedo]) {
         [self.managedObjectContext redo];
         [self.managedObjectContext save:nil];
    }

This makes the "NSUndoManager" really simple to use.

Comments

Popular posts from this blog

Free Hand Drawing on Google's Map View

Android from iOS Guy's Perspective

Free Hand Drawing on Maps with MapBox SDK