列出Swift中的所有窗口名称

时间:2019-04-13 04:43:25

标签: swift macos core-graphics

我正在学习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

2 个答案:

答案 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 ?? "")
}