首页 > 解决方案 > UndoManager.setActionName 未显示在菜单中(SwiftUI macOS)

问题描述

Edit 菜单的 Undo/Redo 显示的标题未反映此演示 SwiftUI macOS 应用程序中的 setActionName 。撤消/重做功能工作正常,管理器报告它已设置操作标题。

为什么菜单没有更新?

NSApp.menu 的 autoenablesItems 是 true。当遍历 NSApp 中的所有窗口(只有一个窗口)时,UndoManager(只有一个用于应用程序)与 SwiftUI 通过 Environment 呈现的实例相同。通过 NSApp 的参考检查撤消项目标题也显示项目标题已设置,即使它没有显示在编辑菜单中。


struct ContentView: View {
    @Binding var document: DocumentTestDocument
    @Environment(\.undoManager) var undo
    @StateObject var vm = VM()
    
    @State var autoEnables = false
    
    var body: some View {
        VStack(spacing: 25) {
            HStack {
                Button("<") { vm.performUndo(undo: undo) }
                    .disabled(!(undo?.canUndo ?? true))
                
                Button("Up") { vm.increment(undo: undo) }
                Button("Down") { vm.decrement(undo: undo) }
                
                Button(">") { vm.performRedo(undo: undo) }
                    .disabled(!(undo?.canRedo ?? true))
            }
            
            Text(String(vm.count))
                .font(.title)
            
            Text("MenuItemTitle \(vm.title)")
            
        }
        .controlSize(.large)
        .font(.title3)
        .frame(width: 400, height:  300)
        .onAppear { DispatchQueue.main.async { autoEnables = NSApp.menu?.autoenablesItems ?? false } }
    }
}

class VM: ObservableObject {
    
    @Published var count = 0
    @Published var title = ""
    
    func increment(undo: UndoManager?) {
        count += 1
        
        undo?.registerUndo(withTarget: self, handler: { (targetSelf) in
            targetSelf.decrement(undo: undo)
        })
        undo?.setActionName("Increment")
        
        title = undo?.undoMenuItemTitle ?? "Nil"
    }
    
    func decrement(undo: UndoManager?) {
        count -= 1
        
        undo?.registerUndo(withTarget: self, handler: { (targetSelf) in
            targetSelf.increment(undo: undo)
        })
        undo?.setActionName("Increment")
        
        title = undo?.undoMenuItemTitle ?? "Nil"
    }
    
    func performUndo(undo: UndoManager?) {
        undo?.undo()
    }
    
    func performRedo(undo: UndoManager?) {
        undo?.redo()
    }
}

标签: macosswiftui

解决方案


出于某种原因,这并没有在新的 SwiftUIApp生命周期中实现。如果您在情节提要中设置 Edit 菜单并自己配置 NSHostingView,则 Undo 菜单项标题将随着您现有的代码正确更改。我当然希望这个功能很快就会出现,因为名副其实的撤消是我最喜欢的抛光 Mac 应用程序的一部分!


推荐阅读