如何在 SwiftUI 中根据前窗口启用/禁用 Mac 菜单项?

问题描述 投票:0回答:1

我正在编写一个应用程序,它有 3 种不同类型的窗口,外加一个设置窗口。某些菜单命令仅影响其中一种窗口类型。

在 AppKit 中,您为菜单项指定一个选择器作为操作,并指定一个 nil 目标。然后,系统沿着响应者链寻找响应该选择器的响应者。如果找到,则会启用该菜单项。如果没有,它将禁用菜单项。这就是你所要做的。

macos swiftui menu
1个回答
0
投票

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。

这很讨厌,但它有效。

如果有人知道一种更优雅(好吧,不那么讨厌)的方法来处理这个问题,我洗耳恭听。

© www.soinside.com 2019 - 2024. All rights reserved.