An undo manager is a framework object for recording changes to object state and later undoing those changes upon user request. The undo manager, which is an instance of the NSUndoManager
class, conducts both undo and redo operations. An undo operation reverts a change to a property of an object; a redo operation restores the original value if an undo operation has taken place. The ability to perform undo and redo operations is a valuable and differentiating feature of applications, especially those that allow users to change data extensively.
You obtain an undo manager through the undoManager
property of UIResponder
(iOS) or by calling the undoManager
method of NSResponder
(Mac OS X). Every window of an application provides a default undo manager, although you can create private ones for specific contexts.
You must register an undo operation with the undo manager. When the undo manager executes the operation, it sends a message composed from several components supplied in registration:
The object to receive the message. The receiving object is typically an object having a property whose value has changed.
The signature of the method to invoke. The signature often identifies a setter accessor method.
The argument of the message. The argument is typically the previous value of the property that has changed. For redo operations, the argument is the changed value.
An undo manager collects all undo operations that occur within a single cycle of a run loop such as the application’s main event loop; executing an undo operation reverts all changes that occurred during the cycle. When performing an undo operation, an undo manager saves the operations that were reverted so that users can redo what has been undone.
An undo manager stores undo and redo operations on first-in last-out stacks. When an application first registers an undo operation, the undo manager adds it to the undo stack. The redo stack, however, remains empty until the user requests an undo operation. When that happens, the undo manager uses the topmost group of operations on the undo stack to compose and send one or more messages to revert changes.
Since these operations again cause changes to one or more object’s state, the objects register new operations with the undo manager, this time in the reverse direction from the original operations. Because the undo manager is currently undoing changes, it records these operations as redo operations on 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. Because a new change to an object’s state invalidates the previous change, as soon as a new undo operation is registered, an undo manager clears the redo stack.
An undo manager collects undo and redo operations in groups that represent actions that are entirely revertible. A group typically identifies properties that are related in some way. It stores these groups of operations as items on the undo and redo stacks. Even a single action must be packaged as a group. NSUndoManager
normally creates undo groups automatically during a cycle of the run loop. The first time it is asked to record an undo operation in the cycle, it creates a new group. Then, at the end of the cycle, it closes the group. You can create additional, nested undo groups.
The NSUndoManager
class gives you two ways to register undo operations:
For simple registration, call registerUndoWithTarget:selector:object:
, which takes a target object, a selector, and a single argument.
For invocation-based registration, call prepareWithInvocationTarget:
, passing in a NSInvocation
object that encapsulates the message to send for reverting changes. With this approach you can have any number and type of arguments.
You often call these methods in the accessor method for a property of an object that is being changed. To request an undo or redo operation, send undo
or redo
message to a NSUndoManager
object.
The responder chain plays an important role in undo management, especially when more than the default undo manager is in play. The responder class in either the UIKit or AppKit frameworks (UIResponder
or NSResponder
) declares the undoManager
property and undoManager
method, respectively. When an application receives an undo event, the responder class starts with the first responder and from there goes up the responder chain looking for an NSUndoManager
object (through the undoManager
property or method). If the end of the responder chain is reached, the window object creates and returns the default undo manager.
If you want an undo manager for a specific context in addition to the default undo manager, your responder subclass can implement the undoManager
property or method to create and return one. The responder subclass is often a custom view but it can also be, on iOS, a view controller (which must ensure that it becomes first responder). In Mac OS X, the delegate of a window object can implement the windowWillReturnUndoManager:
to return an undo manager.
Users request undo and redo operations in Mac OS X and iOS in different ways. In a Mac OS X application, the user chooses an Undo or Redo menu command from the Edit menu. In an iOS application, the user shakes the device. For a shaking motion to function as command, the applicationSupportsShakeToEdit
property of UIApplication
must be set to YES
and there must be an undo manager in an appropriate state. If these conditions apply, the application displays an alert view with buttons for undo and redo. In both iOS and Mac OS X, you can give specific action names to undo and redo commands—for example, Undo Color Change.
Last updated: 2010-07-07