我有一个目标C代码片段,我想用swift表示
CFArrayRef windowList;
AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute, (CFTypeRef *)&windowList);
if ((!windowList) || CFArrayGetCount(windowList)<1)
continue;
AXUIElementRef windowRef = (AXUIElementRef) CFArrayGetValueAtIndex( windowList, 0);
CFTypeRef role;
AXUIElementCopyAttributeValue(windowRef, kAXRoleAttribute, (CFTypeRef *)&role);
第一件事我不确定:谁在windowlistpointer后面分配内存。
我试过这个片段:
var windowListPointer : UnsafeMutablePointer<Optional<AnyObject>>
AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute as CFString, windowListPointer );
但这甚至不能编译:它抱怨WindowListPointer没有初始化。
我可以创建什么对象来让WindowListPointer指向?
最佳答案
如果您最后一次通过一个UnsafeMutablePointer<Optional<AnyObject>>
参数AXUIElementCopyAttributeValue()
则必须
通过分配(并最终释放)内存来初始化它:
var resultPtr: UnsafeMutablePointer<Optional<AnyObject>> = UnsafeMutablePointer.allocate(capacity: 1)
resultPtr.initialize(to: nil)
let result = AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute as CFString, resultPtr)
// ...
resultPtr.deinitialize()
resultPtr.deallocate(capacity: 1)
这比较容易
传递变量的地址
使用
Optional<AnyObject>
。然后有条件地将接收到的对象强制转换为所需的类型,在这种情况下,
&
数组:var value: AnyObject?
let result = AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute as CFString, &value)
if result == .success, let windowList = value as? [AXUIElement] {
// use `windowList`
}
同样地:
if let window = windowList.first {
var value: AnyObject?
let result = AXUIElementCopyAttributeValue(window, kAXRoleAttribute as CFString, &value)
if result == .success, let role = value as? String {
// use `role` ...
}
}
可以定义一个封装
所有铸件:
func axUICopyAttributeValue<T>(of element: AXUIElement, attribute: String, as type: T.Type) -> T? {
var value: AnyObject?
let result = AXUIElementCopyAttributeValue(element, attribute as CFString, &value)
if result == .success, let typedValue = value as? T {
return typedValue
}
return nil
}
示例用法:
if let windowList = axUICopyAttributeValue(of: appRef, attribute: kAXWindowsAttribute, as:[AXUIElement].self) {
for window in windowList {
if let role = axUICopyAttributeValue(of: window, attribute: kAXRoleAttribute, as: String.self) {
// ...
}
}
}