几个月来,我一直在使用此代码块查找某个活动应用程序的窗口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
}
}
}
然而,在最近的一次快速更新中,
takeRetainedValue()
及其对应的takeUnretainedValue()
似乎已被删除。我在网上看到的每一篇关于它的文章都说,只要删除这个调用,就应该让它或多或少地以相同的行为工作,但是当我这样做时,应用程序总是在“for dict in info”行出现可爱的“thread 1:exc_bad_instruction(code=exc_i386_invop,subcode=0x0)”错误时崩溃,循环甚至还没有开始。我花了好几个小时试图解决这个问题,我找到了一堆线索,但没有一个能把我带到任何地方。我已经知道这与删除一个未被管理的对象有关,但我仍在学习,不知道从这里到哪里去。
有没有办法解决我遇到的问题,或者如果没有,我应该完全使用另一种方法?
最佳答案
在swift 2中访问corefoundation对象有一些有趣的变化。您不再需要从CFArray
获取保留或未保留的值,您可以将其直接桥接到swift数组。你得到了一个崩溃,因为你试图在运行时将aCFArray
转换为a[[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
可以被桥接到swiftString
对象,没有问题。最好使用常量,而不是硬编码字符串,因为常量的值可能会随时间而变化。关于swift - CFArray takeRetainedValue()删除导致崩溃,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36140837/