CFArray takeRetainedValue() 删除导致崩溃
CFArray takeRetainedValue() removal causing crashes
几个月来我一直在使用这段代码来查找某个活动应用程序的 window 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()
似乎已被删除。我在网上找到的关于它的每一个 post 都说只要删除调用就应该让它以或多或少相同的行为工作,但是当我这样做时,应用程序总是崩溃并出现可爱的 "Thread 1: EXC_BAD_INSTRUCTION (code=EXC_i386_INVOP, subcode=0x0)" 错误"for dict in info" 行,甚至在循环开始之前。
我花了好几个小时试图解决这个问题,我找到了很多线索,但是 none 其中的线索让我无所适从。我收集到它与删除 takeRetainedValue()
给我留下一个非托管的 CFArray
对象有关,但我仍在学习,并且对于从这里去哪里一无所知。
有什么方法可以解决我遇到的问题,如果没有,我应该完全使用另一种方法吗?
在 Swift 中访问 CoreFoundation 对象有一些时髦的变化。 2. 您不再需要从 CFArray
中获取保留或未保留的值,您可以将其直接桥接到 Swift数组。您遇到崩溃是因为您试图在运行时将 CFArray
转换为 [[String : AnyObject]]
并且它返回 nil
.
CGWindowListCopyWindowInfo
returns CFArray?
(可选 CFArray
)。尝试将 CFArray?
桥接到 [AnyObject]
将失败,但将其桥接到可选的 Swift 数组 ([AnyObject]?
) 将起作用。但是为了遍历该数组,我们必须打开它。在这里,我检查 CGWindowListCopyWindowInfo
返回的 CFArray
是否可以解包并桥接到 [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
returns 为零,我们将不会尝试遍历它。
还要注意 CFString
常量 kCGWindowName
和 kCGWindowNumber
可以桥接到 Swift String
对象没有问题。最好使用常量而不是硬编码字符串,因为常量的值可能会随时间变化。
几个月来我一直在使用这段代码来查找某个活动应用程序的 window 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()
似乎已被删除。我在网上找到的关于它的每一个 post 都说只要删除调用就应该让它以或多或少相同的行为工作,但是当我这样做时,应用程序总是崩溃并出现可爱的 "Thread 1: EXC_BAD_INSTRUCTION (code=EXC_i386_INVOP, subcode=0x0)" 错误"for dict in info" 行,甚至在循环开始之前。
我花了好几个小时试图解决这个问题,我找到了很多线索,但是 none 其中的线索让我无所适从。我收集到它与删除 takeRetainedValue()
给我留下一个非托管的 CFArray
对象有关,但我仍在学习,并且对于从这里去哪里一无所知。
有什么方法可以解决我遇到的问题,如果没有,我应该完全使用另一种方法吗?
在 Swift 中访问 CoreFoundation 对象有一些时髦的变化。 2. 您不再需要从 CFArray
中获取保留或未保留的值,您可以将其直接桥接到 Swift数组。您遇到崩溃是因为您试图在运行时将 CFArray
转换为 [[String : AnyObject]]
并且它返回 nil
.
CGWindowListCopyWindowInfo
returns CFArray?
(可选 CFArray
)。尝试将 CFArray?
桥接到 [AnyObject]
将失败,但将其桥接到可选的 Swift 数组 ([AnyObject]?
) 将起作用。但是为了遍历该数组,我们必须打开它。在这里,我检查 CGWindowListCopyWindowInfo
返回的 CFArray
是否可以解包并桥接到 [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
returns 为零,我们将不会尝试遍历它。
还要注意 CFString
常量 kCGWindowName
和 kCGWindowNumber
可以桥接到 Swift String
对象没有问题。最好使用常量而不是硬编码字符串,因为常量的值可能会随时间变化。