Как правильно использовать CFStringGetCString в Swift? - PullRequest
0 голосов
/ 02 апреля 2019

Я просматриваю документы для CFStringGetCString и AXUIElementCopyAttributeValue .

CFStringGetCString принимает параметр buffer: UnsafeMutablePointer<Int8>! AXUIElementCopyAttributeValue принимает параметр value: UnsafeMutablePointer<CFTypeRef?>

Для последнего я могу позвонить так:

var value: CFTypeRef?
let err = AXUIElementCopyAttributeValue(element, attribute as CFString, &value);

Это удовлетворяет документ, запрашивающий UnsafeMutablePointer типа CFTypeRef.

ОднакоЯ не могу применить ту же логику, выполнив

let buffer: Int8!
CFStringGetCString(attribute as! CFString, &buffer, 2048, CFStringBuiltInEncodings.UTF8.rawValue)

Я также пытался

let buffer: Int8?
CFStringGetCString(attribute as! CFString, &buffer!, 2048, CFStringBuiltInEncodings.UTF8.rawValue)

В любом случае, он жалуется на использование buffer до его инициализации, даже если онникогда не жаловался на value в рабочем методе с аналогичными требованиями к параметрам.

Все рабочие примеры, которые я видел для CFStringGetCString, используют синтаксис, похожий на target-c с *.Не уверен, какой правильный быстрый путь здесь.

Я также пытался получить желаемое значение:

let app = AXUIElementCreateSystemWide();
var valueString = "";

var value: CFTypeRef?
// An exception on execution happens here when passing app
// Passing in the element I clicked instead of app
// yields error -25205 (attributeunsupported)
let err = AXUIElementCopyAttributeValue(app, "AXFocusedApplication" as CFString, &value);
if (err == AXError.success) {
    valueString = value! as! NSString as String;
} else {
    print("ERROR!");
    print(err.rawValue);
}

return valueString;

1 Ответ

0 голосов
/ 03 апреля 2019

Почему ты мучаешь себя с CFStringGetCString? Если у вас есть CFString в Swift, вы можете привести его к String и получить строку C из этого:

let cString: [Int8] = (cfString as String).cString(using: .utf8)!

Обратите внимание также, что значение kAXFocusedApplicationAttribute равно , а не a CFString. Это AXUIElement.

Вот мой тест на игровой площадке:

import Foundation
import CoreFoundation

let axSystem = AXUIElementCreateSystemWide()
var cfValue: CFTypeRef?
AXUIElementCopyAttributeValue(axSystem, kAXFocusedApplicationAttribute as CFString, &cfValue)
if let cfValue = cfValue, CFGetTypeID(cfValue) == AXUIElementGetTypeID() {
    let axFocusedApplication = cfValue
    print(axFocusedApplication)
}

Когда я впервые запустил эту игровую площадку, у меня появилось системное диалоговое окно, в котором говорилось, что мне нужно дать разрешение XCode для управления моим компьютером. Я перешел в «Системные настройки»> «Безопасность и конфиденциальность»> «Конфиденциальность»> «Доступность», нашел XCode внизу списка и включил его флажок.

Вот вывод детской площадки:

<AXUIElement Application 0x7fb2d60001c0> {pid=30253}

Я предполагаю, что вы работаете в macOS, поскольку AXUI API доступен только в macOS. Если вы просто хотите, чтобы имя приложения в виде строки, вы можете сделать это:

if let frontAppName = NSWorkspace.shared.frontmostApplication?.localizedName {
    print(frontAppName)
}
...