SwiftUI UndoManager — 它是如何工作的,它是如何工作的?

问题描述

我正在尝试了解 UndoManager 的工作原理。我做了一个小应用程序来撤消/重做某事。 我有几个问题,我在文档中找不到答案:

  1. 我知道可以通过以下方式在视图中访问 UndoManager

    @Environment(\.undoManager) var undoManager

太棒了。但在这种情况下,它只在视图中可用,如果我想在结构中更深的地方使用它,我必须通过模型将它传递给对象......是一种在其他对象中访问相同 UndoManager 的方法吗?模型,数据...我可以更方便,特别是如果有很多撤消分组。如果我在 Document(或其他地方)中创建 UndoManager,它在主菜单 Edit -> Undo,Redo 中不可见

  1. 在应用 repository on GitHub 中,我实现了撤消/重做。对我来说 (haha) 看起来不错,甚至可以工作,但不适用于第一次行动。第一个操作撤消会导致 Thread 1: signal SIGABRT 错误。三个动作后,我可以撤消最后两个动作……砰。出了点问题

     import Foundation
     import SwiftUI
    
     struct CustomView: View {
         @Observedobject var model: Pointsviewmodel
    
         @Environment(\.undoManager) var undoManager
    
         @GestureState var isDragging: Bool = false
         @State var dragOffsetDelta = CGPoint.zero
    
         var formatter: NumberFormatter {
             let formatter = NumberFormatter()
             formatter.allowsFloats = true
             formatter.minimumFractionDigits = 2
             formatter.maximumFractionDigits = 5
             return formatter
         }
    
         var body: some View {
             HStack {
                 vstack(alignment: .leading,spacing: 10) {
                     ForEach(model.insideDoc.points.indices,id:\.self) { index in
                         HStack {
                             TextField("X",value: $model.insideDoc.points[index].x,formatter: formatter)
                                 .frame(width: 80,alignment: .topLeading)
                             TextField("Y",value: $model.insideDoc.points[index].y,alignment: .topLeading)
                             Spacer()
                         }
    
                     }
                     Spacer()
                 }
             ZStack {
                 ForEach(model.insideDoc.points.indices,id:\.self) { index in
                     Circle()
                         .foregroundColor(index == model.selectionIndex ? .red : .blue)
                         .frame(width: 20,height: 20,alignment: .center)
                         .position(model.insideDoc.points[index])
    
                         //MARK: - drag point
                         .gesture(DragGesture(minimumdistance: 0,coordinateSpace: .local)
                                     .onChanged { drag in
                                         if !isDragging {
                                             dragOffsetDelta = drag.location - model.insideDoc.points[index]
                                             model.selectionIndex = index
                                             let Now = model.insideDoc.points[index]
                                             undoManager?.registerUndo(withTarget: model,handler: { model in
                                                 model.insideDoc.points[index] = Now
                                                 model.objectwillChange.send()
                                             })
                                             undoManager?.setActionName("undo Drag")
                                         }
                                         model.insideDoc.points[index] = drag.location - dragOffsetDelta
                                     }
                                     .updating($isDragging,body: { drag,state,trans in
                                         state = true
                                         model.objectwillChange.send()
                                     })
                                     .onEnded({drag in model.selectionIndex = index
                                         model.insideDoc.points[index] = drag.location - dragOffsetDelta
                                         model.objectwillChange.send()
                                     })
                         )
    
                 }
             }.background(Color.orange.opacity(0.5))
    
             //MARK: - new point
             .gesture(DragGesture(minimumdistance: 0,coordinateSpace: .local)
                         .onEnded{ loc in
                             let prevIoUsIndex = model.selectionIndex
                             undoManager?.registerUndo(withTarget: model,handler: {model in
                                 model.insideDoc.points.removeLast()
                                 model.selectionIndex = prevIoUsIndex
                                 model.objectwillChange.send()
                             })
                             model.insideDoc.points.append(loc.location)
                             model.selectionIndex = model.insideDoc.points.count - 1
                             model.objectwillChange.send()
                         }
    
             )
    
             //MARK: - delete point
             .onReceive(deleteSelectedobject,perform: { _ in
                 if let deleteIndex = model.selectionIndex {
                     let deleted = model.insideDoc.points[deleteIndex]
                     undoManager?.registerUndo(withTarget: model,handler: {model in
                         model.insideDoc.points.insert(deleted,at: deleteIndex)
                         model.objectwillChange.send()
                     })
                     undoManager?.setActionName("remove Point")
                     model.insideDoc.points.remove(at: deleteIndex)
                     model.objectwillChange.send()
                     model.selectionIndex = nil
                 }
             })
    
         }
         }
     }
    

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)