Block Based Undo/Redo Api in SwiftUI

Related Articles

When building applications in macOS and iOS, it is recommended to include undo / re-run support within your app. SwiftUI provides @Environment (.undoManager) It reveals a UndoManager However to register cancellation actions in the principal we need to pass a grade.

We can use UndoManager However, this will cause the cancellation operations to continue in the cancellation stack even after the user has moved to another view. I have already discussed the UndoProvider based solution I use Clora In some situations, however, it is easier to perform an explicit cancellation and execution operation.

To this end we can define a propertyWrapper Who catches UndoManager And reveals the method we need.

struct UndoProxy: DynamicProperty 
  var wrappedValue = UndoProxyObject()
  var projectedValue
  mutating func update() 
    self.wrappedValue.undoManager = self.projectedValue

Compatible with DynamicProperty Means SwiftUI will call ours update A method that gives us the opportunity to assign the UndoManger goddess UndoProxyObject.

In the above UndoProxy A cover we use UndoProxyObject.

class UndoProxyObject: ObservableObject 
  weak var undoManager: UndoManager?
  func `do`(
    _ doBlock: @escaping () -> Void,
    undo undoBlock: @escaping () -> Void
    undoManager?.registerUndo(withTarget: self)  target in, undo: doBlock)

UndoProxyObject Provides single do A method that can be read with do and undo Blocks. It performs the do Block and then record an undo An action that turns the do and undo Blocks so that do Block becomes redo Action when then undo Applied.

A good example of UndoProxy Your views are designed to add the ability to undelete items.

struct ContentView: View {
  var undoProxy
  var body: some View 
    ForEach(users)  user in
    .onDelete  indices in

      var removedUsers: [User] = []
      for index in indices 
        users.remove(atOffsets: indices)
        for (index, indexInList) in indices.enumerated() 
          users.insert(removedUsers[index], at: indexInList)



Please enter your comment!
Please enter your name here

Popular Articles