Search code examples
iphoneundo-redonsundomanager

Undo/Redo using NSUndoManager in iPhone SDK


I have been trying to design the Undo/Redo functionality in one of my app using NSUndoManager class and seeing some design difficulties. In my app, I just have one method

-(IBAction) addLastBall:(Ball *)ball

So, when a user chooses a button in the UI, I add a ball object to my array list. However, I don't have any action button to remove a ball, this is the design of the UI workflow and can't be changed. So, to implement a undo I called the following piece of code inside the addLastBall method

[undoManager registerUndoWithTarget:self selector:@selector(removeBall:) object:ball];

After doing this, removeBall method gets called with the ball object when the user tried to perform the undo. All is good for now. But, I am not sure how to handle the redo part now, when the user tries to redo, I am not sure which method would get called, because I need to add the ball object the user just removed using the undo operation. Any insights would be very helpful.

Thanks so much.


Solution

  • A redo simply performs the undo actions registered while the corresponding undo was executing. Therefore, the most straightforward solution is to simply to register an undo action in the removeBall: method.

    - (void)removeBall:(Ball *)ball {
        [undoManager registerUndoWithTarget:self 
                                   selector:@selector(addLastBall:)
                                     object:ball];
        ...
    }
    

    Note that it is sometimes clearer to useprepareWithInvocationTarget: to register undo actions:

    [[undoManager prepareWithInvocationTarget:self] addLastBall:ball];
    

    By the way, be sure to keep the retain count of the ball above zero in the removeBall: method — the undo manager will not retain the ball for you, and if it gets deallocated, then undoing the remove will crash.