几个月来,我一直在使用此代码块查找某个活动应用程序的窗口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常量kCGWindowNamekCGWindowNumber可以被桥接到swiftString对象,没有问题。最好使用常量,而不是硬编码字符串,因为常量的值可能会随时间而变化。

关于swift - CFArray takeRetainedValue()删除导致崩溃,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36140837/

10-11 09:09