You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在AXObserverCallback回调中保留AXUIElementRef以便外部复用?

问题描述

我尝试存储AXObserverCallback回调提供的AXUIElementRef,但当回调作用域结束后,该结构体似乎被释放,导致无法在其他地方使用。请问是否有办法将该引用保留或复制到自定义数据结构中?

相关代码如下:

AXObserverCreate(..., &observer_callback, ...);
AXObserverAddNotification(..., ..., kAXWindowCreatedNotification, this);
...
void observer_callback(AXObserverRef observer, AXUIElementRef windowRef,
                       CFStringRef notificationName, void* inUserData) {
    applications* apps = (applications*)inUserData;

    if (CFEqual(notificationName, kAXWindowCreatedNotification)) {
        // memory error when trying to use windowRef outside of callback
        apps->add_window_ref(windowRef);
    } else if (CFEqual(notificationName, kAXUIElementDestroyedNotification)) {
        apps->remove_window_ref(windowRef);
    }
}

已知在Swift中可实现该需求,例如某开源项目已采用相关做法。


解决方案

AXUIElementRef属于*Core Foundation(CF)*对象,遵循CF的手动内存管理规则。回调中拿到的windowRef是临时引用,回调结束后系统会自动释放它,直接存储会触发野指针错误。要保留这个引用,必须手动管理它的引用计数:

1. 存储时保留引用

在add_window_ref方法中调用CFRetain(windowRef)增加引用计数,确保对象不会被系统提前释放:

void applications::add_window_ref(AXUIElementRef windowRef) {
    // 保留引用,维持对象生命周期
    CFRetain(windowRef);
    // 将引用存入自定义数据结构(示例用vector)
    window_refs.push_back(windowRef);
}

2. 不再使用时释放引用

当你确定不再需要该AXUIElementRef(比如收到销毁通知或清理数据结构时),调用CFRelease(windowRef)减少引用计数,避免内存泄漏:

void applications::remove_window_ref(AXUIElementRef windowRef) {
    // 从数据结构中移除目标引用
    auto it = std::find(window_refs.begin(), window_refs.end(), windowRef);
    if (it != window_refs.end()) {
        window_refs.erase(it);
        // 释放引用,平衡计数
        CFRelease(windowRef);
    }
}

关键注意事项

  • 严格遵循CF内存管理原则:谁调用CFRetain,谁就要负责调用CFRelease,保证引用计数始终平衡。
  • 收到kAXUIElementDestroyedNotification时,对应的AXUIElementRef已经失效,释放后绝对不能再访问该对象。
  • Swift中能自动处理,是因为Swift的ARC会自动为桥接的CF对象管理引用计数,本质和手动调用CFRetain/CFRelease逻辑一致。

内容的提问来源于stack exchange,提问作者Jason1923

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 19:16:24