Search code examples
objective-ccocoaundo-redonsundomanagerredo

Clearing NSUndoManager's Redo stack


In my application, there are some actions I want to undo programmatically, without giving the user the option of clicking "Redo". Is there any way to clear the Redo stack of NSUndoManager? If not, and I were to subclass NSUndoManager, is there any way to get access to the redo stack in order to clear it? I didn't see any way to from the documentation.

Alternately, is there a way to revert the changes from the current nested undo group without it populating the Redo stack? I'm already building a nested undo group.


Solution

  • I ended up taking a 2-step approach. The first step was to create a dummy undo item, which clears the Redo stack. Then, I just had to remove that undo item, and both stacks are clean.

    I was able to use self as the dummy undo target, since I don't have any actual undo actions associated with the class containing the code. self could be replaced with any object that doesn't contribute to the Undo stack.

    The trick was calling removeAllActionsWithTarget with a delay, otherwise it doesn't have an effect.

    // End the open undo grouping
    [undoManager endUndoGrouping];
    
    // Perform the undo operation, which gets pushed onto the Redo stack
    [undoManager undo];
    
    // Add a dummy Undo item to clear the Redo stack
    [undoManager registerUndoWithTarget:self selector:nil object:nil];
    
    // Remove the dummy item with a delay, pushing it to the next run loop cycle
    [undoManager performSelector:@selector(removeAllActionsWithTarget:)
                      withObject:self
                      afterDelay:0.0];