UndoController

Swift

@objc(PSPDFUndoController)
public protocol UndoController

A type that keeps track of undoable commands and works together with the system undo manager to provide the undo/redo functionality for documents.

You can use the undo controller to record new commands, and you can use the underlying undo manager to actually perform undo/redo.

Recording Commands

The undo/redo stacks contain commands that consist of one or more actions. You can add new commands to the undo stack by asking the undo controller for a recorder and using it to record multiple actions.

undoController.recordCommand(named: "Replace Annotation") { recorder in
    recorder.record(removing: [squareAnnotation]) {
        document.remove(annotations: [squareAnnotation])
    }
    recorder.record(adding: [circleAnnotation]) {
        document.add(annotations: [circleAnnotation])
    }
}

If you want to record a new command that consists only of one type of action, you can use the convenience functions instead.

undoController.recordCommand(named: "Change Font Size", changing: [freeTextAnnotation]) {
    freeTextAnnotation.fontSize = 32
    freeTextAnnotation.sizeToFit()
}

If you want to record actions that happen asynchronously over time, you can ask the undo controller for a detached recorder instead and commit it at the end.

let recorder = undoController.beginRecordingCommand(named: "Rotate Annotation", changing: [stampAnnotation])
// Allow the user to rotate the stamp annotation.
recorder.commit()

Undone commands automatically end up on the redo stack. You can’t add new commands to the redo stack yourself.

Performing Undo and Redo

The undo controller integrates with the system undo manager to provide the best and most natural undo/redo experience. Use it to check if undo/redo is possible and to perform it.

if undoController.undoManager.canUndo {
    undoController.undoManager.undo()
}

Observing Stacks

You can observe the undo manager’s notifications if you need to respond to changes in the undo/redo stack. See the documentation of UndoManager for the complete list of observable notifications.

PSPDF_EXPORT(PSPDFUndoController)

  • The underlying undo manager that can be exposed in a responder chain to enable undo/redo functionality.

    You can use this undo manager to register your own custom actions but be aware that your actions might be removed and the state of this undo manager reset if an error occurs.

    Declaration

    Swift

    var undoManager: UndoManager { get }
  • Record an undoable command with the given localized name and actions recorded in the scope of the given closure.

    An undoable command is added to the undo stack right after execution of the given closure, provided that at least one action was recorded.

    Note

    Recording a new undoable command will invalidate the stack of redoable commands.

    Declaration

    Swift

    @objc(recordCommandNamed:inScope:)
    func recordCommand(named name: String?, in scope: (_ recorder: UndoRecorder) -> Void)

    Parameters

    name

    Localized name of the command that will be used in UI. To display “Undo Change Font Size”, set this to “Change Font Size”. If nil or empty, a simple “Undo” title will be used instead.

    scope

    Closure in which undoable actions are recorded. The passed-in recorder can be used to record actions.

  • Record an undoable command with the given localized name, recording actions of changing multiple properties of the given annotations by observing changes made to them in the scope of the given closure.

    Note

    Recording a new undoable command will invalidate the stack of redoable commands.

    Precondition

    Each of the given annotations must already be referenced in a PDF document, otherwise they will be ignored.

    Declaration

    Swift

    @objc(recordCommandNamed:changingAnnotations:inScope:)
    func recordCommand(named name: String?, changing annotations: [Annotation], in scope: () -> Void)

    Parameters

    name

    Localized name of the command that will be used in UI. To display “Undo Change Thickness”, set this to “Change Thickness”. If nil or empty, a simple “Undo” title will be used instead.

    annotations

    Annotations expected to change.

    scope

    Closure in which annotations are changed.

  • Record an undoable command with the given localized name, recording actions of adding the given annotations to a document.

    Note

    Recording a new undoable command will invalidate the stack of redoable commands.

    Declaration

    Swift

    @objc(recordCommandNamed:addingAnnotations:inScope:)
    func recordCommand(named name: String?, adding annotations: [Annotation], in scope: () -> Void)

    Parameters

    name

    Localized name of the command that will be used in UI. To display “Undo Add Square”, set this to “Add Square”. If nil or empty, a simple “Undo” title will be used instead.

    annotations

    Annotations expected to be added.

    scope

    Closure in which annotations are added to a document.

  • Record an undoable command with the given localized name, recording actions of removing the given annotations from a document.

    Note

    Recording a new undoable command will invalidate the stack of redoable commands.

    Declaration

    Swift

    @objc(recordCommandNamed:removingAnnotations:inScope:)
    func recordCommand(named name: String?, removing annotations: [Annotation], in scope: () -> Void)

    Parameters

    name

    Localized name of the command that will be used in UI. To display “Undo Remove Note”, set this to “Remove Note”. If nil or empty, a simple “Undo” title will be used instead.

    annotations

    Annotations expected to be removed.

    scope

    Closure in which annotations are removed from a document.

  • Begin recording an undoable command with the given localized name and actions recorded during the lifetime of the returned recorder.

    An undoable command is added to the undo stack right after committing the returned recorder, provided that at least one action was recorded.

    Note

    Recording a new undoable command will invalidate the stack of redoable commands.

    Declaration

    Swift

    @objc(beginRecordingCommandNamed:)
    func beginRecordingCommand(named name: String?) -> DetachedUndoRecorder

    Parameters

    name

    Localized name of the command that will be used in UI. To display “Undo Move Annotation”, set this to “Move Annotation”. If nil or empty, a simple “Undo” title will be used instead.

    Return Value

    Object that can be used to record actions. This object is not owned by the callee and must be retained by the caller.

  • Begin recording an undoable command with the given localized name, recording actions of changing multiple properties of the given annotations by observing changes made to them during the lifetime of the returned recorder.

    Note

    Recording a new undoable command will invalidate the stack of redoable commands.

    Note

    The returned recorder retains strong references to the given annotations until it’s committed.

    Precondition

    Each of the given annotations must already be referenced in a PDF document, otherwise they will be ignored.

    Declaration

    Swift

    @objc(beginRecordingCommandNamed:changingAnnotations:)
    func beginRecordingCommand(named name: String?, changing annotations: [Annotation]) -> PendingUndoRecorder

    Parameters

    name

    Localized name of the command that will be used in UI. To display “Undo Resize Annotation”, set this to “Resize Annotation”. If nil or empty, simple “Undo” title will be used instead.

    annotations

    Annotations expected to change.

    Return Value

    Object that records changes to the given annotations upon committing. This object is not owned by the callee and must be retained by the caller.