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.
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.