CFArray takeRetainedValue()删除导致崩溃

时间:2016-03-21 20:22:36

标签: swift macos cocoa swift2 core-graphics

我已经使用这段代码来查找某个活动应用程序的窗口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对象有关,但我仍然在学习,并且对于哪里无能为力离开这里。

有没有办法解决我遇到的问题,或者如果不是,我应该完全使用另一种方法?

1 个答案:

答案 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常量kCGWindowNamekCGWindowNumber可以桥接到Swift String对象没问题。使用常量比使用硬编码字符串更好,因为常量的值可能会随着时间而变化。