【问题标题】:Accessing Objective-C Pointers in Swift在 Swift 中访问 Objective-C 指针
【发布时间】:2017-11-25 14:44:38
【问题描述】:

我有这个 Objective-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 指向?

【问题讨论】:

  • @MartinR TNT,如示例中的var windowList : CFArray? AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute as CFString, &amp;windowList ) 也无法编译:无法传递“CFTypeRef”类型的不可变值? (aka 'Optional') as inout

标签: objective-c swift pointers


【解决方案1】:

如果您将 UnsafeMutablePointer&lt;Optional&lt;AnyObject&gt;&gt; 作为最后一个传递 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&lt;AnyObject&gt; 变量的地址 与&amp;。然后有条件 将接收到的对象转换为预期的类型,在这种情况下是 AXUIElement 的数组:

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) {

            // ...
        }
    }
}

【讨论】:

  • 谢谢!两个问题,1)我在哪里可以找到,我必须转换为 [AXUIElement] 2)var value: AnyObject? 该声明是为 Object 分配任何内存还是只是对 AnyObject(或 nil)的引用
  • 1) developer.apple.com/documentation/applicationservices/… 声明这些值是“可访问性对象的数组”。 – 2) 可选变量被隐式初始化为nil。那里没有分配内存。
  • 现在编译正常,但返回 AXError 。得到了这篇文章中的其他参数:stackoverflow.com/questions/47480873/…
  • AXError的行值为kAXErrorCannotComplete = -25204,Doku说:发生了根本性错误,例如处理过程中分配内存失败。有没有可能,我必须为var value: AnyObject? 分配任何东西?
  • 对不起,我不知道。我参考了当前应用程序let appRef = AXUIElementCreateApplication(getpid()) 对其进行了测试,结果奏效了。
【解决方案2】:

CFArray 是 NSArray 的 Foundation C 版本(因为 C 不理解 Objective C NSObjects)。为您提供 NSArray 和 CFArray 的 Swift 文件,因此您无需使用指针;您应该能够使用as? 将其转换为适当类型的 Swift 数组

【讨论】:

  • 你会为`AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute as CFString, windowList)'中的windowList使用什么Swift类型
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-04
  • 1970-01-01
  • 2010-12-02
  • 1970-01-01
相关资源
最近更新 更多