将 NSAccessibilityElement 添加到现有的 NSView

Add NSAccessibilityElement to an existing NSView

我想在我的应用程序中使用 MacOS accessibility feature,它呈现自己的自定义 UI(即不使用 Cocoa)。为此,我实现了与我绘制的每个小部件相关联的子类 NSAccessibilityElement 树。 根 UI 容器托管在外部提供给我的应用程序的 NSView 中(我的应用程序是一个插件)。现在我需要将 NSAccessibilityElement 的树附加到主机提供的现有 NSView

Apple documentation 推荐两种实现方式:

NSAccessibilityElement 的树附加到现有 NSView 的正确方法是什么?

所以我最终子类化 NSView 以捕获顶层 NSAccessibilityElement。重写 - (NSArray*) accessibilityChildren 方法 returns 将可访问性元素捕获为其子元素之一:

@interface AccessibilityRootView : NSView
- (instancetype)initWithAccessibilityElement: (NSAccessibilityElement*)anElement;
@end

@implementation AccessibilityRootView
{
    NSAccessibilityElement* element;
}

- (instancetype) initWithAccessibilityElement: (NSAccessibilityElement*)anElement
{
    self = [super init];

    if (self)
        element = anElement;

    return self;
}

- (NSArray*) accessibilityChildren
{
    NSArray<NSAccessibilityElement*> *children = [super accessibilityChildren];

    int numKids = (int)[children count] + 1;
    NSMutableArray<NSAccessibilityElement*> *kids = [NSMutableArray<NSAccessibilityElement*> arrayWithCapacity:numKids];

    for (id object in children)
        [kids addObject:object];

    [kids addObject: element];

    return NSAccessibilityUnignoredChildren (kids);
}
@end

然后我将这个零大小的子类视图附加到主机提供的父 NSView

NSView* hostView = /* host-provided NSView */;
AccessibilityRootView* accessibilityRootView = [[AccessibilityRootView alloc] initWithAccessibilityElement:(NSAccessibilityElement*)topLevelAccessibilityElement];
[hostView addSubview:accessibilityRootView];
[accessibilityRootView release];

此时我的所有 NSAccessibilityElements 都附加到主机提供的视图中的那个零大小视图,MacOS 可以成功查询项目。

此外,每个 NSAccessibilityElement 都必须正确实施其 - (NSRect)accessibilityFrame- (id) accessibilityHitTest:(NSPoint)point 以匹配我自定义绘制的 UI 小部件的屏幕位置。