如何通过macOS无障碍API在WebKit应用中实现文本选择
macOS 无障碍API实现WebKit视图文本选中方案
基于kAXSelectedTextRangeAttribute的CFRange选中文本逻辑,仅对原生Cocoa文本控件生效。Apple Mail撰写窗口这类基于WebKit渲染的内容区域,文本元素为Static Text类型,不暴露上述属性,必须通过AXTextMarker系列API完成主动选中文本操作。
AXTextMarker、AXTextMarkerRange是WebKit内部维护的不透明类型,无公开直接构造方法,必须通过目标元素暴露的无障碍属性、参数化接口生成,无法手动创建实例。
实现流程
- 前置校验
操作前先确认目标元素的AXSelectedTextMarkerRange属性可写,避免无效调用:var settable: DarwinBoolean = false AXUIElementIsAttributeSettable(targetElement, kAXSelectedTextMarkerRangeAttribute as CFString, &settable) guard settable.boolValue else { return } - 获取指定偏移位置的TextMarker
调用参数化属性kAXTextMarkerForIndexParameterizedAttribute,传入整数偏移值,返回对应文本位置的AXTextMarker实例:func textMarker(at offset: Int, for element: AXUIElement) throws -> AnyObject { var marker: AnyObject? let res = AXUIElementCopyParameterizedAttributeValue( element, kAXTextMarkerForIndexParameterizedAttribute as CFString, NSNumber(value: offset) as CFTypeRef, &marker ) guard res == .success, let valid = marker else { throw AXError.failure } return valid } - 生成选中范围TextMarkerRange
拿到选中文本的起始、结束位置Marker后,调用参数化属性kAXTextMarkerRangeForUnorderedTextMarkersParameterizedAttribute,传入两个Marker组成的数组,返回合法的选中范围对象,接口会自动处理Marker顺序,无需手动比较位置:func markerRange(start: AnyObject, end: AnyObject, for element: AXUIElement) throws -> AnyObject { var range: AnyObject? let res = AXUIElementCopyParameterizedAttributeValue( element, kAXTextMarkerRangeForUnorderedTextMarkersParameterizedAttribute as CFString, [start, end] as CFArray, &range ) guard res == .success, let valid = range else { throw AXError.failure } return valid } - 触发选中
将生成的MarkerRange赋值给目标元素的kAXSelectedTextMarkerRangeAttribute属性,即可完成选中文本操作:func selectText(start: Int, end: Int, for element: AXUIElement) throws { let startM = try textMarker(at: start, for: element) let endM = try textMarker(at: end, for: element) let range = try markerRange(start: startM, end: endM, for: element) let setRes = AXUIElementSetAttributeValue( element, kAXSelectedTextMarkerRangeAttribute as CFString, range ) guard setRes == .success else { throw AXError.failure } }
兼容性说明
AXTextMarker、AXTextMarkerRange实例与生成它的AXUIElement强绑定,跨元素、跨应用复用会直接调用失败。- 传入的字符偏移不能超过文本总长度,可通过读取元素
kAXNumberOfCharactersAttribute属性获取总长度做边界校验。 - 旧版本macOS若找不到对应属性常量,可直接使用字符串值调用:
- 索引转Marker参数属性:
"AXTextMarkerForIndex" - 双Marker生成Range参数属性:
"AXTextMarkerRangeForUnorderedTextMarkers" - 选中范围属性:
"AXSelectedTextMarkerRange"
- 索引转Marker参数属性:
内容的提问来源于stack exchange,提问作者Schurigeln
相关产品推荐
相关产品推荐

