Date:

Share:

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 administrator, we must pass a lesson.

We can use UndoManager However, this will cause the cancellation operations to continue in the cancellation stack even after the user has switched to another view. I’ve already talked about 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.

@propertyWrapper
struct UndoProxy: DynamicProperty 
   
  @StateObject
  var wrappedValue = UndoProxyObject()
   
  @Environment(.undoManager)
  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
  ) 
    doBlock()
    undoManager?.registerUndo(withTarget: self)  target in
      target.do(undoBlock, 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 {
  @UndoProxy
  var undoProxy
   
  ...
   
  var body: some View 
    ForEach(users)  user in
      ...
    .onDelete  indices in

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

Source

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Popular Articles