OS X:如果应用程序已经 运行 无头(通过 NSApplicationActivationPolicyProhibited),则从 dock 启动应用程序是空操作

OS X: Launching app from dock is a no-op if app is already running headless (via NSApplicationActivationPolicyProhibited)

我的应用程序可以 运行 与 UI 和 运行 无头,通过命令行参数选择。 (我不想构建两个单独的应用程序。)当 运行ning 无头时,我正在调用:

[NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];

在应用程序初始化期间,不显示任何 windows。

一切正常,我可以 运行 应用程序同时有头(通过扩展坞)和无头(通过另一个应用传递命令行参数)。小点仅在带头应用程序的停靠栏图标旁边显示。好的。如果先启动无头应用程序,就会出现问题。在那种状态下(停靠栏中没有点),任何点击应用程序图标(或通过 Spotlight 或 Finder 启动)都不会执行任何操作,或者有时会弹出 "You can’t open the application “Foo” because it is not responding." 大概 OS 认为该应用程序已经运行ning 为首,正在尝试激活它。有没有办法说服它忽略那个后台应用程序并启动一个新实例?

退出后台应用程序可让应用程序再次从 Dock 正常启动。

我不想在 plist 中设置 LSBackgroundOnly,因为这将需要两个单独的应用程序,除非我在 headed 应用程序的情况下将 setActivationPolicy 更改为 NSApplicationActivationPolicyRegular。但我读到 会导致其他各种错误,例如菜单栏并不总是显示。

有什么想法吗?

我在 OS 10.10.5(最旧的 OS 我需要支持)。感谢您的帮助!

更新:我刚刚注意到,当点击停靠栏时它似乎什么也没做,如果没有应用程序 windows 打开我可以看到它实际上取消隐藏我的应用程序的主要 window (这是隐藏创建的)但没有将它带到前面(大概它注意到 NSApplicationActivationPolicyProhibited 已设置,尽管这不足以阻止它显示 window!)。

更新 2:在这一点上,我会找到一种方法来通知用户该应用程序未启动的原因是他们需要退出已子启动无头进程的其他应用程序。当然,这段代码需要在无头应用程序中,因为有头应用程序甚至不会启动。

看起来您可以从 applicationShouldHandleReopen 调用 setActivationPolicy 并在那时将策略设置回 NSApplicationActivationPolicyRegular。我使用以下代码制作了一个测试应用程序,它的行为似乎与您在上面描述的一样(尽管我在 10.11.5 上只 运行 它):

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        if NSUserDefaults.standardUserDefaults().stringForKey("background") == "true" {
            NSApp.setActivationPolicy(.Prohibited)
            print("launched in background")
        }
    }

    func applicationShouldHandleReopen(sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
        NSApp.setActivationPolicy(.Regular)
        return true
    }

}