真正的问题
你如何更新mainMenu
在 SwiftUI 中,它真的可以工作吗?
我在 SwiftUI 中构建了一个基于 MacOS 文档的应用程序,其中包括所有内置的文件菜单命令(即关闭、保存、复制、重命名...等)
在保存文档之前,我会验证结构,并希望在存在任何验证错误时向用户显示模式对话框。
模式对话框只是一个简单的“确定/取消”对话框 - “确定”意味着用户很乐意保存带有验证错误的文件,“取消”则需要停止保存操作。
所以问题是:“如何拦截内置的‘保存’菜单命令来显示此对话框?
我试图覆盖.saveItem
CommandGroup - 但这取代了all菜单项,我只想覆盖几个命令(“保存”和“另存为”),并且不想重新实现所有命令(而且我不确定我是否有能力这样做)
.commands {
CommandGroup(replacing: .saveItem) {
// code goes here - but removes all of the in-built menus
}
}
我已经尝试过这个解决方案(在 SwiftUI 文档应用程序中,如何从函数内保存文档 https://stackoverflow.com/questions/68522523/in-a-swiftui-document-app-how-to-save-a-document-from-within-a-function)
并将其放入我的 AppDelegate 中
public func applicationDidBecomeActive(_ notification: Notification) {
let menu = NSApplication.shared.mainMenu!.items.first(where: { $0.title == "File" })!
let submenu = menu.submenu!.items.first(where: { $0.title == "Save" })!
submenu.action = #selector(showDialog)
}
@objc func showDialog() {
var retVal: Int = 0
let thisWindow: NSWindow? = NSApplication.shared.mainWindow
let nsAlert: NSAlert = NSAlert()
let cancelButton: NSButton = nsAlert.addButton(withTitle: "Cancel")
cancelButton.tag = 1
let okButton: NSButton = nsAlert.addButton(withTitle: "OK")
okButton.tag = 0
// The below code is replaced
nsAlert.beginSheetModal(for: thisWindow!) { modalResponse in
print(modalResponse)
retVal = modalResponse.rawValue
if retVal == 0 {
print("save")
} else {
print("cancel")
}
}
}
然而它实际上并没有调用showDialog
功能。
编辑/更新
我在更新菜单时仍然遇到困难,但在上面的示例中调用beginModalSheet
是不正确的,因为该进程将在后台运行。将调用更新为runModal()
这将停止写入文件的任何后台进程。
@objc func showDialog() {
let nsAlert: NSAlert = NSAlert()
let cancelButton: NSButton = nsAlert.addButton(withTitle: "Cancel")
cancelButton.tag = 1
let okButton: NSButton = nsAlert.addButton(withTitle: "OK")
okButton.tag = 0
let response: Int = nsAlert.runModal().rawValue
if response == 0 {
print("save")
NSApp.sendAction(#selector(NSDocument.save(_:)), to: nil, from: nil)
} else {
print("cancel")
}
}
我在某处读到您需要在窗口出现之前设置菜单,并且我还读到您需要在设置 AppDelegate 之前设置菜单。
另一个编辑
看这个帖子隐藏 SwiftUI / MacOS 应用程序的编辑菜单 https://stackoverflow.com/questions/71309874/hiding-edit-menu-of-a-swiftui-macos-app
和这个评论
Thoughts:SwiftUI 要么有错误,要么他们真的不希望您删除 NSApp.mainMenu 中的顶级菜单。 SwiftUI 似乎重置了整个菜单,目前无法覆盖或自定义大多数细节(Xcode 13.4.1)。 CommandGroup(replacing: .textEditing) { } 式命令不允许您删除或清除整个菜单。当 SwiftUI 需要时,即使您没有指定任何命令,分配一个新的 NSApp.mainMenu 也会被破坏。