如何使 macOS 应用程序窗口在关闭后隐藏,并通过菜单栏项重新打开?

4

我正在开发一款macOS应用程序(使用Swift和Storyboard),其窗口的行为类似于Adobe Creative Cloud应用程序。但是经过多个小时的研究后,我仍然无法找到最优解决方案。

这意味着:

  1. 当应用程序启动时,主窗口将显示各种菜单项,状态栏中会出现一个图标,而在Dock中也会出现一个图标。
  2. 当用户单击红色X时,主窗口和Dock中的图标将被隐藏。
  3. 可以通过单击状态栏图标来重新打开主应用程序窗口,并重新出现Dock图标。

我的Storyboard如下所示: enter image description here

我尝试过以下方法:

  1. 通过将“Application is agent (UIElement)”设置为“YES”,我能够关闭主应用程序窗口,同时保持应用程序运行。但是,应用程序图标不会出现在Dock中,状态栏左侧也没有菜单项。

  2. 通过单击状态栏图标,我可以启动一个新的应用程序窗口。但是,这样做只会打开一个全新的窗口,而不管当前是否已经显示了一个窗口(我只想显示一个窗口)。

let storyboard = NSStoryboard(name: "Main", bundle: nil)
guard let window = storyboard.instantiateController(withIdentifier: .init(stringLiteral: "main")) as? WindowController else { return }
window.showWindow(self)

非常感谢能够提供帮助的人!

我已经阅读了你的问题。是什么让你认为我没有阅读? - Willeke
@Willeke 这个问题是关于从菜单栏中的 NSStatusItem 停用和启用应用程序,包括隐藏/显示 Dock 图标,而您建议的重复问题是关于标准关闭和打开窗口的情况。 - Ely
@Wendel:请在你的问题末尾添加“项目”,以防止重复投诉。 - Ely
是的,我本可以更好地描述我的问题,但它并不是重复的。 - Wendell
显示剩余2条评论
1个回答

4

不要使用“Application is agent”方法,而是更改NSApp的activationPolicy。

为了在关闭(最后)窗口后动态隐藏图标,请在您的AppDelegate中使用以下内容:

func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
    NSApp.setActivationPolicy(.accessory)
    return false
}

使用类似以下代码初始化菜单栏图标并激活窗口,包括一个dock图标:

class ViewController: NSViewController {

    var status: NSStatusItem?

    override func viewDidLoad() {
        super.viewDidLoad()

        status = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
        status?.button?.title = "Test"
        status?.button?.action = #selector(activateWindow(_:))
        status?.button?.target = self
    }

    @IBAction func activateWindow(_ sender: AnyObject) {
        NSApp.setActivationPolicy(.regular)
        DispatchQueue.main.async {
            NSApp.windows.first?.orderFrontRegardless()
        }
    }
}

是的,这几乎是我所需要的。但是,在运行activateWindow之后,窗口没有重新出现。应用程序图标确实出现在Dock中,并且菜单也会显示在状态栏中。 - Wendell
我使用了if let window = NSApp.windows.first {来检查NSApp.windows.first,并且它不是nil... - Wendell
@Wendell 尝试使用 window.makeKeyAndOrderFront(nil) - Ely
@Wendell 我稍微扩展了我的答案。只需将此粘贴到新项目中即可。我已在自己的电脑上测试过,运行的是macOS 11。 - Ely
是的,你的解决方案在我创建的新项目中确实有效。我会把它给你! - Wendell
显示剩余2条评论

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