Manage undo and redo operations in CE.SDK programmatically, subscribe to history changes, and use multiple independent history stacks for isolated editing contexts.
CE.SDK automatically tracks editing operations, enabling users to undo and redo changes. The engine creates undo steps for most operations automatically. You can also create multiple independent history stacks to isolate editing contexts — for example, separate histories for a main canvas and an overlay editor.
Setup#
We start by creating a scene and page. The engine automatically creates a history stack when it initializes.
let scene = try engine.scene.create()let page = try engine.block.create(.page)try engine.block.setWidth(page, value: 800)try engine.block.setHeight(page, value: 600)try engine.block.appendChild(to: scene, child: page)Subscribing to History Changes#
Use engine.editor.onHistoryUpdated to receive notifications when the history state changes. The stream fires after any undo, redo, or new operation, making it straightforward to keep custom UI elements in sync.
let historyTask = Task { for await _ in engine.editor.onHistoryUpdated { let canUndo = try engine.editor.canUndo() let canRedo = try engine.editor.canRedo() print("History updated — canUndo: \(canUndo), canRedo: \(canRedo)") }}Cancel the Task when you no longer need notifications, such as when dismissing a view.
Automatic Undo Step Creation#
Most editing operations automatically create undo steps. Adding a block to the scene records this operation in the history stack.
let block = try engine.block.create(.graphic)try engine.block.setShape(block, shape: engine.block.createShape(.rect))try engine.block.setWidth(block, value: 100)try engine.block.setHeight(block, value: 100)try engine.block.setFill(block, fill: engine.block.createFill(.color))try engine.block.appendChild(to: page, child: block)After creating the block, canUndo() returns true.
Performing Undo and Redo#
Use engine.editor.undo() and engine.editor.redo() to revert or restore changes. Always check availability with canUndo() and canRedo() first.
if try engine.editor.canUndo() { try engine.editor.undo()}After undoing, canRedo() returns true. Call redo() to restore the change.
if try engine.editor.canRedo() { try engine.editor.redo()}Managing Undo Steps Manually#
Most operations are tracked automatically. For custom operations that the engine doesn’t track, use addUndoStep() to create a checkpoint manually.
try engine.block.setWidth(block, value: 200)try engine.editor.addUndoStep()Use removeUndoStep() to discard the most recent undo step without affecting the redo stack.
if try engine.editor.canUndo() { try engine.editor.removeUndoStep()}Working with Multiple History Stacks#
CE.SDK supports multiple independent history stacks. This is useful when different parts of your app need separate undo/redo histories. Only the active history responds to undo/redo operations.
let primaryHistory = engine.editor.getActiveHistory()let secondaryHistory = engine.editor.createHistory()engine.editor.setActiveHistory(secondaryHistory)
// Operations here only affect secondaryHistorytry engine.block.setWidth(block, value: 300)
engine.editor.setActiveHistory(primaryHistory)engine.editor.destroyHistory(secondaryHistory)- Create a stack with
createHistory()and activate it withsetActiveHistory() - Operations while a stack is active only affect that stack
- Always call
destroyHistory()when a stack is no longer needed to free resources
API Reference#
| Method | Purpose |
|---|---|
engine.editor.createHistory() | Create a new undo/redo history stack |
engine.editor.destroyHistory(_:) | Destroy a history stack and free resources |
engine.editor.setActiveHistory(_:) | Set a history stack as the active one |
engine.editor.getActiveHistory() | Get the currently active history stack |
engine.editor.addUndoStep() | Manually add a checkpoint to the undo stack |
engine.editor.removeUndoStep() | Remove the most recent undo step |
engine.editor.undo() | Revert to the previous history state |
engine.editor.redo() | Restore the next history state |
engine.editor.canUndo() | Check if an undo operation is available |
engine.editor.canRedo() | Check if a redo operation is available |
engine.editor.onHistoryUpdated | Subscribe to history change notifications |
Next Steps#
- Events — subscribe to block creation, update, and deletion events
- Editor State — track selection and edit mode changes
- Scenes — create and manage design scenes