UndoManager 的 canUndo 属性未在 SwiftUI 中更新

Poi*_*urn 5 nsundomanager swiftui

当堆栈中有操作时,为什么不@Environment UndoManager更新其属性?canUndo我有一个视图,它的子视图可以利用取消/重做功能,但由于某种原因,我无法根据管理器禁用撤消按钮。

struct MyView: View {
    @Environment(\.undoManager) var undoManager: UndoManager?

    var body: some View {
        Button("Undo") { ... }
            .disabled(!self.undoManager!.canUndo)
    }
}
Run Code Online (Sandbox Code Playgroud)

Asp*_*eri 14

UndoManager.canUndo不兼容 KVO,因此使用一些通知发布者来跟踪状态,如下所示

struct MyView: View {
    @Environment(\.undoManager) var undoManager
    @State private var canUndo = false

    // consider also other similar notifications
    private let undoObserver = NotificationCenter.default.publisher(for: .NSUndoManagerDidCloseUndoGroup)

    var body: some View {
        Button("Undo") { }
            .disabled(!canUndo)
            .onReceive(undoObserver) { _ in
                self.canUndo = self.undoManager!.canUndo
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @PaulOllivier 如果您在接收 NSUndoManagerCheckpoint 时查询 canRedo 这将导致无限循环,因为 canRedo 会触发检查点通知:“每当 NSUndoManager 对象打开或关闭撤消组(除非它打开顶级组时)以及检查canRedo 中的重做堆栈。” (7认同)
  • 我发现这与 [ ***private let undoObserver = notificationCenter.default.publisher(for: .NSUndoManagerCheckpoint)*** ] 配合使用效果更好,然后您就可以正确获取 canUndo 和 canRedo 状态 (2认同)