为什么 activate(ignoringOtherApps:) 不启用菜单栏?

Why doesn't activate(ignoringOtherApps:) enable the menu bar?

Whosebug 上有很多 tutorials/questions/answers 关于能够使用简单程序启动 GUI 应用程序,而无需创建应用程序包和 Info.plist。其中大部分使用 Objective-C 方法 [NSApp activateIgnoringOtherApps:true] 将应用程序带到前台,以及 [NSWindow makeKeyAndOrderFront:] 将 windows 带到前台。

问题似乎是在 macOS 10.15 版本上,菜单栏只有在您第一次离开该应用程序并再次返回时才会启用。我已经设法将问题减少到以下几行 Swift:

// Run this, click on the Apple logo in the top left
// You cannot get the Apple system menu until you tab
// to another application and back again
import AppKit

var app = NSApplication.shared
app.setActivationPolicy(.regular)
app.activate(ignoringOtherApps: true)
app.run()

当这是运行作为命令行应用程序时,无法选择左上角的苹果菜单。如果您从该应用程序切换然后再返回,它会起作用。

添加windows并执行makeKeyAndOrderFront没有效果;您可以添加它们,并且 window 确实获得了焦点 - 但是在您切换 away/back.

之前菜单栏不会启用

同样令人困惑的是,如果您创建一个目录 Example.app/Contents/MacOS,然后将上面的二进制文件复制进去,并使用 open 启动应用程序,那么菜单会在第一次启动时立即生效。区别似乎在于从终端与 LaunchServices 启动应用程序的方式。

有什么方法可以修复这个最小的示例,以便菜单立即运行吗?

为了便于复制,我已将代码推送到 https://github.com/alblue/Bugger 并且有一个 makefile 可以从命令行 (make run) 和通过应用程序包 (make app).

我设法找到了一个简单的解决方法;将激活移动到 applicationDidFinishLaunching 委托中:

import AppKit

@objc
class Delegate: NSObject, NSApplicationDelegate {
        func applicationDidFinishLaunching(_ notification: Notification) {
                app.setActivationPolicy(.regular)
                app.activate(ignoringOtherApps: true)
        }
}

var app = NSApplication.shared
let delegate = Delegate()
app.delegate = delegate
app.run()

此更改后,菜单可点击。

对于 10.15,对 setActivationPolicy 的调用也需要在 applicationDidFinishLaunching 回调中。