【问题标题】:OS X: Launching app from dock is a no-op if app is already running headless (via NSApplicationActivationPolicyProhibited)OS X:如果应用程序已经无头运行(通过 NSApplicationActivationPolicyProhibited),则从 Dock 启动应用程序是无操作的
【发布时间】:2016-09-15 22:37:38
【问题描述】:

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

[NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];

在应用初始化期间,不显示任何窗口。

这一切都很好,我可以同时运行有头(通过扩展坞)和无头(通过另一个应用程序传递命令行参数)的应用程序。小点仅显示在主应用程序的停靠图标旁边。好的。如果首先启动无头应用程序,则会出现问题。在这种状态下(dock 中没有点),任何单击应用程序图标(或通过 Spotlight 或 Finder 启动)都不会执行任何操作,或者有时会显示“您无法打开应用程序“Foo”,因为它没有响应。 "大概操作系统认为该应用程序已经在运行,并正在尝试激活它。有没有办法说服它忽略该后台应用并启动一个新实例?

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

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

有什么想法吗?

我使用的是 OS 10.10.5(我需要支持的最旧的操作系统)。感谢您的帮助!

更新:我刚刚注意到,当单击 Dock 时,它似乎什么也不做,如果没有打开应用程序窗口,我可以看到它实际上取消隐藏了我的应用程序的主窗口(它被创建为隐藏)但没有带来它在前面(大概它注意到 NSApplicationActivationPolicyProhibited 已设置,尽管这还不足以阻止它显示窗口!)。

更新 2:此时,我会选择一种方法来通知用户该应用未启动的原因是他们需要退出已分启动无头进程的另一个应用。当然,这段代码需要在 headless 应用中,因为 headed 甚至不会启动。

【问题讨论】:

  • 您是否考虑过为长时间运行的任务使用单独的可执行文件?
  • 是的,如果我找不到解决方案,这就是我必须做的,但我更希望有一个可执行文件。
  • 您是否检查过是否获得了在用户单击停靠图标时调用的应用程序委托方法?我不记得它的名字了——也许名字中带有“重新激活”的东西。
  • 见下面的applicationShouldHandleReopen

标签: macos cocoa launch headless


【解决方案1】:

看起来您可以从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
    }

}

【讨论】:

  • applicationShouldHandleReopen 是一个很好的提示——我正要为其添加一个处理程序,但发现我的应用程序已经有了一个!这是显示主窗口的原因。但是,删除它并不能解决问题:停靠栏点击仍然是无效的。而且我实际上并不希望无头应用程序成为有头应用程序,而是希望启动一个新的有头实例。但这给了我一个地方可以这样做或显示错误消息。谢谢!
猜你喜欢
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
  • 2015-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-30
相关资源
最近更新 更多