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

时间:2019-12-06 19:13:02

标签: swift macos macos-catalina

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

让我们想象一下,我找到了一个名为“ Finder”的应用程序。此应用目前为:

Not active和/或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{ $0.localizedName = "NameOfApp"}

2次运行的代码结果:

  
      
  1. isActive:false; isHidden:假
  2.   
  3. isActive:false; isHidden:假
  4.   
  5. isActive:true; isHidden:假
  6.   
  7. isActive:true; isHidden:假
  8.   

如果您愿意尝试...:

  1. 代码将显示给我该应用程序的菜单: enter image description here

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

  3. 不会向我显示应用程序窗口! (为什么?)

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

以SourceTree应用为例。


有人可以在任何情况下通过一些代码来解释运行的应用程序中任何一个的逻辑和显示窗口吗?

1 个答案:

答案 0 :(得分:2)

此处正在运行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 $0.localizedName == self.filterName || $0.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()