SwiftUI - 如何在 macOS 上使用 onCommand 和 NSMenuItem?

10

我正在尝试找到将NSMenuItem与macOS上的SwiftUI onCommand连接起来的最佳解决方案。

目前,我正在执行以下操作:

  1. 在AppDelegate中,我创建了一个虚拟函数,以便能够列出第一响应者接收到的动作列表。
@IBAction func changeColor(_ sender: Any) {
    print("Dummy Function")
}
  1. 在 Main.storyboard 中创建并连接一个具有 First Responder 功能的 NSMenuItem。

  2. 向我的 SwiftUI 视图添加所需的代码。

struct TestView: View {

    let changeColor = #selector(AppDelegate.changeColor(_:))

    var body: some View {
        VStack {
            TextField("Text", text: .constant(""))
            Text("Hello World!")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .onCommand(changeColor) {
            print("Change Color Action")
        }
    }
}

如果TextField是第一响应者,那么我会看到打印出“Change Color Action”的信息。 如果TextField之前不是第一响应者,则视图不会成为第一响应者。也许这是Catalina Beta(19A558d)中当前存在的一个bug,因为我无法使可聚焦性起作用。

你能否重新表述一下结束段落,更清晰地描述问题? - Bill
嘿,这与你的问题无关,但是你是否使用SwiftUI构建了你的NSMenu - Faruk
你最终解决了这个问题吗?我也遇到了类似的情况,很想知道你是否有任何进展。 - UberJason
2个回答

3

我通过首先使视图可聚焦,已经成功实现了这一点:

struct TestView: View {

    let changeColor = #selector(AppDelegate.changeColor(_:))

    var body: some View {
        VStack {
            TextField("Text", text: .constant(""))
            Text("Hello World!")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .focusable() // Add this 
        .onCommand(changeColor) {
            print("Change Color Action")
        }
    }
}

如果您想使用键盘导航在控件之间移动,则还需要检查键盘系统偏好设置中的“使用键盘导航在控件之间移动”复选框。

enter image description here


谢谢你的回答。我知道有偏好设置,但不是很多用户会打开这个设置(我也不会)。在正常的 macOS 开发中,你可以使任何自定义视图成为第一响应者,而无需打开此功能。我仍在寻找一个完全令人满意的解决方案。 - Marc T.
这似乎起到了作用,但onCommand和那个设置之间有什么联系呢? - Bill
@Bill 在 SwiftUI 的 onCommand 文档字符串中,它说:“视图或其包含的一个视图必须处于焦点状态才能触发操作...”.focusable() 和该设置必须允许这样吗?尽管如此,我仍然无法使其工作。 - Austin
我尝试复制您的示例,但对我来说它不起作用!它只调用了@IBAction func changeColor,而从未调用onCommand(changeColor)。我很想看到onCommand修饰符的真实用例! :) - Vitya Shurapov

1
我最终在我的AppDelegate中创建了一个PassthroughSubject,将其传递给我的SwiftUI视图,并在由SwiftUI视图拥有的模型对象中订阅它。当我的AppDelegate选择器调用菜单命令时,我使用PassthroughSubject发送事件,我的模型接收并适当处理。
我的答案肯定不是理想的,如果您找到更好的方法,请告诉我。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接