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次运行编码结果:
- isActive: false; isHidden: false
- isActive: false; isHidden: false
- isActive: true; isHidden: false
- isActive: true; isHidden: false
如果你愿意尝试...:
代码将显示应用程序的菜单:
但仅在第二个代码上 运行! (为什么?)
- 不会显示应用 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()
我看到 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次运行编码结果:
- isActive: false; isHidden: false
- isActive: false; isHidden: false
- isActive: true; isHidden: false
- isActive: true; isHidden: false
如果你愿意尝试...:
代码将显示应用程序的菜单:
但仅在第二个代码上 运行! (为什么?)
- 不会显示应用 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()