swift - 等待应用程序窗口打开后再继续
问题描述
我想在 Swift 中打开一个应用程序并等待应用程序窗口打开,然后再继续。
我正在使用以下方法打开应用程序:
func openApp(appPath: String, callback: @escaping (NSRunningApplication) -> Void) {
let conf = NSWorkspace.OpenConfiguration();
NSWorkspace.shared.openApplication(
at: URL.init(fileURLWithPath: appPath),
configuration: conf
) { app, err in
callback(app!)
}
}
// relevant code inside another function:
if (app == nil)
guard let appPath = NSWorkspace.shared.absolutePathForApplication(withBundleIdentifier: bundleId) else { throw MyError.runtimeError("no app path")}
do {
let group = DispatchGroup()
try app = NSWorkspace.shared.launchApplication(at: URL.init(fileURLWithPath: appPath), options: [], configuration: [:])
group.enter()
openApp(appPath: appPath) { (newApp) in
app = newApp;
group.leave();
}
group.wait();
} catch {
throw MyError.runtimeError("failed to launch");
}
}
在稍后阶段,我需要使用该应用程序的窗口:
extension AXUIElement {
func getAttribute<T>(key: String) -> T {
var ptr: AnyObject?
AXUIElementCopyAttributeValue(self, "AX\(key)" as CFString, &ptr)
if key == "Size" || key == "Position" {
let val = ptr as! AXValue
return val.toValue()
}
return ptr as! T
}
func setAttribute<T: AnyObject>(key: String, value: T) {
AXUIElementSetAttributeValue(self, "AX\(key)" as CFString, value)
}
}
let axApp = AXUIElementCreateApplication(app!.processIdentifier)
let windows: [AXUIElement] = axApp.getAttribute(key: kAXWindowsAttribute) as [AXUIElement];
但是当应用程序启动时,此代码会在实际窗口打开之前执行。所以我收到以下错误:
Could not cast value of type 'Swift.Optional<Swift.AnyObject>' (0x7fff8e6b2cd8) to 'Swift.Array<__C.AXUIElementRef>' (0x7fff8e6b2c78).
如何在执行代码获取窗口实例之前等待窗口打开
解决方案
我最近遇到了同样的问题。我想在打开应用程序后调整窗口大小并重新定位窗口位置。这是我在 Swift 5 中的解决方案。
NSWorkspace.shared.open(fileURLs,
withApplicationAt: appUrl,
configuration: config) { runningApp, error in
guard error == nil else { return }
while true {
//wait for application actual finished launch
Thread.sleep(forTimeInterval: 0.1)
guard let isFinish = runningApp?.isFinishedLaunching,
let isActivate = runningApp?.isActive,
isFinish && isActivate else { continue }
//Your code here
break
}
}
}