我已经使用这段代码来查找某个活动应用程序的窗口ID数月了:
let info = CGWindowListCopyWindowInfo(CGWindowListOption(kCGWindowListOptionAll), CGWindowID(0)).takeRetainedValue()
for dict in info as! [ [ String : AnyObject ] ] {
if let windowName = dict["kCGWindowName"] as? String{
if(windowName == "MyWindowName"){
let windowID = dict["kCGWindowNumber"] as! Int
println("found window, window number: \(windowID)")
return
}
}
}
截至最近的Swift更新,takeRetainedValue()
及其对应takeUnretainedValue()
似乎已被删除。关于它的每一篇文章,我都能找到,只是删除调用应该让它或多或少地处理相同的行为,但是当我这样做时,应用程序总是崩溃与可爱的"线程1:EXC_BAD_INSTRUCTION(代码= EXC_i386_INVOP) ,子码= 0x0)" "对于信息中的字典错误"在循环之前甚至可以开始。
我花了好几个小时试图解决这个问题,而且我找到了很多线索,但没有一个人带我去任何地方。我已经知道它与takeRetainedValue()
删除了一个无法管理的CFArray
对象有关,但我仍然在学习,并且对于哪里无能为力离开这里。
有没有办法解决我遇到的问题,或者如果不是,我应该完全使用另一种方法?
答案 0 :(得分:3)
在Swift 2中访问CoreFoundation对象有一些时髦的变化。您不再需要从CFArray
获取保留或未保留的值,您可以将其直接桥接到Swift数组。您因为在运行时尝试将CFArray
投放到[[String : AnyObject]]
并且正在返回nil
而导致崩溃。
CGWindowListCopyWindowInfo
返回CFArray?
(可选CFArray
)。尝试将CFArray?
桥接到[AnyObject]
会失败,但将其桥接到可选的Swift数组([AnyObject]?
)将会起作用。但是为了遍历那个数组,我们必须解开它。在这里,我检查CFArray
返回的CGWindowListCopyWindowInfo
是否可以解包并桥接到[AnyObject]!
:
if let info = CGWindowListCopyWindowInfo(.OptionAll, CGWindowID(0)) as [AnyObject]! {
for dict in info {
if let windowName = dict[kCGWindowName as String] as? String {
if (windowName == "MyWindowName"){
let windowID = dict[kCGWindowNumber as String] as? Int
print("found window, window number: \(windowID)")
break
}
}
}
}
如果由于某种原因CGWindowListCopyWindowInfo
返回nil,我们就不会尝试迭代它。
另请注意,CFString
常量kCGWindowName
和kCGWindowNumber
可以桥接到Swift String
对象没问题。使用常量比使用硬编码字符串更好,因为常量的值可能会随着时间而变化。