我正在学习Swift。如何修复以下代码以列出窗口名称?
import CoreGraphics
let windows = CGWindowListCopyWindowInfo(CGWindowListOption.optionAll, kCGNullWindowID)
for i in 0..<CFArrayGetCount(windows) {
if let window = CFArrayGetValueAtIndex(windows, i) {
print(CFDictionaryGetValue(window, kCGWindowName))
}
}
错误:
main.swift:6:32: error: cannot convert value of type 'UnsafeRawPointer' to expected argument type 'CFDictionary?'
print(CFDictionaryGetValue(window, kCGWindowName))
^~~~~~
as! CFDictionary
答案 0 :(得分:2)
如果避免使用Core Foundation类型和方法,并尽可能早地将值桥接到本机Swift类型,则变得更加容易。
在这里,CGWindowListCopyWindowInfo()
返回CFArray
中可选的CFDictionaries
,并且可以桥接到相应的Swift类型[[String : Any]]
。然后,您可以使用常用的Swift方法(数组枚举和字典下标)访问其值:
if let windowInfo = CGWindowListCopyWindowInfo(.optionAll, kCGNullWindowID) as? [[ String : Any]] {
for windowDict in windowInfo {
if let windowName = windowDict[kCGWindowName as String] as? String {
print(windowName)
}
}
}
答案 1 :(得分:1)
您可以使用unsafeBitCast(_:to:)
将不透明的原始指针转换为CFDictionary
。请注意,您还需要将第二个参数转换为原始指针:
CFDictionaryGetValue(unsafeBitCast(window, to: CFDictionary.self), unsafeBitCast(kCGWindowName, to: UnsafeRawPointer.self))
unsafeBitCast(_:to:)告诉编译器将该变量视为另一种类型,但是它不是很安全(因此使用unsafe
前缀),建议阅读文档以获取更多详细信息,尤其是以下注意事项:< / p>
警告
调用此函数破坏了Swift类型系统的保证;使用时要格外小心。
在特定情况下,使用该函数应该不会有任何问题,因为您正在使用适当的类型,如您正在调用的Foundation
函数的文档中所声明。
完整,可行的代码如下所示:
import CoreGraphics
let windows = CGWindowListCopyWindowInfo(CGWindowListOption.optionAll, kCGNullWindowID)
for i in 0..<CFArrayGetCount(windows) {
let windowDict = unsafeBitCast(CFArrayGetValueAtIndex(windows, i), to: CFDictionary.self)
let rawWindowNameKey = unsafeBitCast(kCGWindowName, to: UnsafeRawPointer.self)
let rawWindowName = CFDictionaryGetValue(windowDict, rawWindowNameKey)
let windowName = unsafeBitCast(rawWindowName, to: CFString?.self) as String?
print(windowName ?? "")
}