Перечислите все имена окон в Swift - PullRequest
0 голосов
/ 13 апреля 2019

Я учу Свифта.Как мне исправить следующий код для перечисления имен окон?

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 ]

2 голосов
/ 13 апреля 2019

Это станет проще, если вы будете избегать использования типов и методов 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 голос
/ 13 апреля 2019

Вы можете использовать unsafeBitCast(_:to:) для преобразования непрозрачного необработанного указателя в CFDictionary. Обратите внимание, что вам также необходимо преобразовать второй параметр в необработанный указатель:

CFDictionaryGetValue(unsafeBitCast(window, to: CFDictionary.self), unsafeBitCast(kCGWindowName, to: UnsafeRawPointer.self))

unsafeBitCast (_: to:) указывает компилятору обрабатывать эту переменную как другой тип, однако это не очень безопасно (таким образом, префикс unsafe), рекомендуя прочитать документацию для получения более подробной информации, особенно следующее примечание:

Внимание

Вызов этой функции нарушает гарантии системы типов 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 ?? "")
}
...