Swift: 如何激活和取消隐藏任何应用程序的 window?

Swift: How to activate and unhide window of ANY application?

我看到 NSRunningApplicationInstance.activate() 方法的行为很奇怪。

假设我找到了名为 "Finder" 的应用程序。此应用目前是:

Not active and/or hidden

我的代码非常简单:

let activeOptions: NSApplication.ActivationOptions = [.activateAllWindows, .activateIgnoringOtherApps]

print("1. isActive: \(app.isActive); isHidden: \(app.isHidden)")
if (!app.isActive)
{
   app.activate(options: activeOptions)
}

if ( app.isHidden )
{
   app.unhide()
}
print("2. isActive: \(app.isActive); isHidden: \(app.isHidden)")

要查找需要的应用,您可以使用以下代码:

let app = NSWorkspace.shared.runningApplications.filter{ [=13=].localizedName = "NameOfApp"}

2次运行编码结果:

  1. isActive: false; isHidden: false
  2. isActive: false; isHidden: false
  3. isActive: true; isHidden: false
  4. isActive: true; isHidden: false

如果你愿意尝试...:

  1. 代码将显示应用程序的菜单:

  2. 但仅在第二个代码上 运行! (为什么?)

  3. 不会显示应用 window! (为什么?)

我发现很多应用程序都有类似的行为,不仅仅是 Finder。

例如 SourceTree 应用程序。


有人可以解释逻辑以及如何在任何情况下通过某些代码显示 运行 任何应用程序的 window 吗?

这是工作中的 Playground 模块。该方法是将 KVO 用于可观察的属性,以便在目标应用程序的确切期望状态出现时得到通知。希望能有所帮助。

import Cocoa

class AppActivator: NSObject {

    private var application: NSRunningApplication!
    private let filterName: String

    init(appName: String) {
        filterName = appName
    }

    func activate() {
        guard let app = NSWorkspace.shared.runningApplications.filter ({
            return [=10=].localizedName == self.filterName || [=10=].bundleIdentifier?.contains(self.filterName) ?? false
        }).first else {
            print("Application \(self.filterName) not found")
            return
        }

        guard app.activationPolicy != .prohibited else {
            print("Application \(self.filterName) prohibits activation")
            return
        }

        self.application = app

        self.unhideAppIfNeeded()
        self.activateAppIfNeeded()
    }

    private func unhideAppIfNeeded() {
        if application.isHidden {
            application.addObserver(self, forKeyPath: "isHidden", options: .new, context: nil)
            application.unhide()
        }
    }

    private func activateAppIfNeeded() {
        if !application.isHidden && !application.isActive {
            application.addObserver(self, forKeyPath: "isActive", options: .new, context: nil)
            application.activate(options: .activateIgnoringOtherApps)
        }
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "isHidden" {
            application.removeObserver(self, forKeyPath: "isHidden")
            activateAppIfNeeded()
        } else if keyPath == "isActive" {
            application.removeObserver(self, forKeyPath: "isActive")
            print("Application \(application.localizedName) - ACTIVATED!")
        }
    }
}

let activator = AppActivator(appName: "Finder")
activator.activate()