5

I have an app where I want to save the current state of a project before every change so that undo and redo will be able to step back and forth within those states. When I make a change the code to save the position is:

if(!undoManager){
    undoManager = [[NSUndoManager alloc] init];
}
[[undoManager prepareWithInvocationTarget:self] replaceSelf:currentState];

And my undo/redo functions:

-(void)undo{
    if(undoManager){
        [undoManager disableUndoRegistration];
        [undoManager undo];
        [undoManager enableUndoRegistration];
    }
}
-(void)redo{
    if(undoManager){
        [undoManager disableUndoRegistration];
        [undoManager redo];
        [undoManager enableUndoRegistration];
    }
}

The replace self function just takes the project state property and distributes the information so that the state is restored.

Undo works perfect, i can perform 5 steps and then hit undo 5 times to rewind to the start, but redo does nothing at all! Shouldn't invoking redo cause it to hit my selector with the last object that was undone? What am I misunderstanding here?

box86rowh
  • 3,415
  • 2
  • 26
  • 37

1 Answers1

0

I got this working, in the replaceSelf function that was being called by the undo/redo, I added this code:

[undoManager registerUndoWithTarget:self selector:@selector(replaceSelf:) object:ps];

Where ps is the current project state before the undo/redo is done. This got it working for me!

box86rowh
  • 3,415
  • 2
  • 26
  • 37
  • This works, but does anyone have explanations why this works? – TheAmateurProgrammer Jun 23 '14 at 07:45
  • 1
    Turns out that this is Apple's design, but I didn't see it in the docs and apparrently many others also missed it. When you receive a call to your undo selector, push an undo state. I think that this is semantically wrong, but who cares? – dfl Nov 30 '15 at 16:26