我正在编写一个应用程序,它有 3 种不同类型的窗口,外加一个设置窗口。某些菜单命令仅影响其中一种窗口类型。
在 AppKit 中,您为菜单项指定一个选择器作为操作,并指定一个 nil 目标。然后,系统沿着响应者链寻找响应该选择器的响应者。如果找到,则会启用该菜单项。如果没有,它将禁用菜单项。这就是你所要做的。
SwiftUI 并不真正支持使用响应者链或发送选择器。
至少不是真的。
问题 1: 您可以使用菜单命令尝试使用
tryToPerform(_:with:)
将选择器发送到对象,并且您可以使用 Appkit NSApp.keyWindow?.firstResponder
来发送选择器,但是 使用 接收选择器的 SwiftUI 方式.onCommand(Selector(("updateDisplayMode:")))
,不允许您访问附加到发送命令的对象。
问题 2: 没有干净的方法来查看响应者链是否响应选择器。
我想出的是添加一个具有
ObservableObject
属性的全局 <@Published
状态对象 shudder!> 。这些属性之一是 bool
keyWindowIs<type>
。我的每个窗口类型都实现一个 .onChange(of: controlActiveState)
处理程序。在该处理程序中,如果新状态是 .key,它会在我的 ObservableObject
中设置适合该窗口的全局属性。这些属性之一是我的 keyWindowIs<type>
旗帜。
我还必须通过添加
来订阅窗口
willCloseNotification
s
.onReceive(NotificationCenter.default.publisher(for: NSWindow.willCloseNotification, object: window))
我的视图层次结构中顶级对象的处理程序。 (我使用了导航堆栈。)在该窗口中将关闭 onReceive 处理程序,我设置全局状态变量以禁用对当前窗口类型有效的菜单项。
然后,在我的菜单结构中,我将
.disabled(!appSettings.keyWindowIs<type>)
修改器应用于需要根据当前关键窗口启用/禁用的对象(按钮、选择器等)。
因此,每个窗口都会维护全局
appSettings.keyWindowIs<type>
标志,因为它成为关键,并且当窗口关闭时,它会将该窗口类型的标志设置为 false。
这很讨厌,但它有效。
如果有人知道一种更优雅(好吧,不那么讨厌)的方法来处理这个问题,我洗耳恭听。