NSUndoManager is a general-purpose recorder of operations for undo and redo. You register an undo operation by specifying the object that is changing (or the owner of that object), along with a method to invoke to revert its state, and the arguments for that method. NSUndoManager groups all operations within a single cycle of the run loop, so that performing an undo reverts all changes that occurred during the loop. Also, when performing undo an NSUndoManager saves the operations reverted so that you can redo the undos.
NSUndoManager is implemented as a class of the Foundation framework because executables other than applications might want to revert changes to their states. For example, you might have an interactive command-line tool with undo and redo commands; or there could be Distributed Object implementations that can revert operations “over the wire.” However, users typically see undo and redo as application features. The Application Kit implements undo and redo in its NSTextView object and makes it easy to implement it in objects along the responder chain. For more on the role of the Application Kit in undo and redo, see “Using Undo in Applications.”
Undo Operations and Groups
The Undo and Redo Stacks
An undo operation is a method for reverting a change to an object, along with the arguments needed to revert the change (for example, its state before the change). Undo operations are typically collected in undo groups, which represent whole revertible actions, and are stored on a stack. Redo operations and groups are simply undo operations stored on a separate stack (described below). When an NSUndoManager performs undo or redo, it is actually undoing or redoing an entire group of operations. For example, a user could change the type face and the font size of some text. An application might package both attribute-setting operations as a group, so when the user chooses Undo, both type face and font size are reverted. To undo a single operation, it must still be packaged in a group.
NSUndoManager normally creates undo groups automatically during
the run loop. The first time it is asked to record an undo operation
in the run loop, it creates a new group. Then, at the end of the
loop, it closes the group. You can create additional, nested undo groups
within these default groups using the beginUndoGrouping
and enableUndoRegistration
methods.
You can also turn off the default grouping behavior using setGroupsByEvent:
.
Undo groups are stored on a stack, with the oldest groups
at the bottom and the newest at the top. The undo stack is unlimited
by default, but you can restrict it to a maximum number of groups
using the setLevelsOfUndo:
method. When
the stack exceeds the maximum, the oldest undo groups are dropped
from the bottom.
Initially, both stacks are empty. Recording undo operations adds to the undo stack, but the redo stack remains empty until undo is performed. Performing undo causes the reverting operations in the latest group to be applied to their objects. Since these operations cause changes to the objects’ states, the objects presumably register new operations with the NSUndoManager, this time in the reverse direction from the original operations. Since the NSUndoManager is in the process of performing undo, it records these operations as redo operations on the redo stack. Consecutive undos add to the redo stack. Subsequent redo operations pull the operations off the redo stack, apply them to the objects, and push them back onto the undo stack.
The redo stack’s contents last as long as undo and redo
are performed successively. However, because applying a new change
to an object invalidates the previous changes, as soon as a new
undo operation is registered, the redo stack is cleared. This prevents
redo from returning objects to an inappropriate prior state. You
can check for the ability to undo and redo with the canUndo
and canRedo
methods.
© 2002 Apple Computer, Inc. All Rights Reserved. (Last updated: 2002-11-12)