列出 Swift 中的所有 window 个名字
List all window names in Swift
我在学习Swift。如何修复以下代码以列出 window 个名称?
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
您可以使用 unsafeBitCast(_:to:)
将不透明的原始指针转换为 CFDictionary
。请注意,您还需要将第二个参数转换为原始指针:
CFDictionaryGetValue(unsafeBitCast(window, to: CFDictionary.self), unsafeBitCast(kCGWindowName, to: UnsafeRawPointer.self))
unsafeBitCast(_:to:) 告诉编译器将该变量视为另一种类型,但是它不是很安全(因此 unsafe
前缀),建议阅读文档以获取更多详细信息,尤其是以下注释:
Warning
Calling this function breaks the guarantees of the Swift type system; use with extreme care.
在您的特定情况下,使用该函数应该没有任何问题,因为您正在使用适当的类型,正如您正在调用的 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 ?? "")
}
更新
您可以通过从一开始就强制转换来更快地将 CoreFoundation 数组引入 Swift 世界:
let windows = CGWindowListCopyWindowInfo(CGWindowListOption.optionAll, kCGNullWindowID) as? [[AnyHashable: Any]]
windows?.forEach { window in
print(window[kCGWindowName])
}
代码可读性强,但它可能会带来性能问题,因为转换为 [[AnyHashable: Any]]` 对于由大型字典组成的大型数组来说可能代价高昂。
如果您避免使用 Core Foundation 类型和方法,并尽早将值桥接到本机 Swift 类型,就会变得更容易。
这里,CGWindowListCopyWindowInfo()
returns 一个 CFDictionaries
的可选 CFArray
,可以桥接到相应的 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)
}
}
}
我在学习Swift。如何修复以下代码以列出 window 个名称?
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
您可以使用 unsafeBitCast(_:to:)
将不透明的原始指针转换为 CFDictionary
。请注意,您还需要将第二个参数转换为原始指针:
CFDictionaryGetValue(unsafeBitCast(window, to: CFDictionary.self), unsafeBitCast(kCGWindowName, to: UnsafeRawPointer.self))
unsafeBitCast(_:to:) 告诉编译器将该变量视为另一种类型,但是它不是很安全(因此 unsafe
前缀),建议阅读文档以获取更多详细信息,尤其是以下注释:
Warning
Calling this function breaks the guarantees of the Swift type system; use with extreme care.
在您的特定情况下,使用该函数应该没有任何问题,因为您正在使用适当的类型,正如您正在调用的 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 ?? "")
}
更新 您可以通过从一开始就强制转换来更快地将 CoreFoundation 数组引入 Swift 世界:
let windows = CGWindowListCopyWindowInfo(CGWindowListOption.optionAll, kCGNullWindowID) as? [[AnyHashable: Any]]
windows?.forEach { window in
print(window[kCGWindowName])
}
代码可读性强,但它可能会带来性能问题,因为转换为 [[AnyHashable: Any]]` 对于由大型字典组成的大型数组来说可能代价高昂。
如果您避免使用 Core Foundation 类型和方法,并尽早将值桥接到本机 Swift 类型,就会变得更容易。
这里,CGWindowListCopyWindowInfo()
returns 一个 CFDictionaries
的可选 CFArray
,可以桥接到相应的 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)
}
}
}