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

iOS UIKit:如何让元素仅对自动化暴露而非无障碍访问?

无障碍与自动化测试配置问题

现有代码实现

@IBOutlet weak var dataDisclosureView: UIStackView! // Main ContainerView

@IBOutlet private weak var titleLabel: UILabel! {
    didSet {
        titleLabel.text = "Hello"
    }
}
    
@IBOutlet private weak var descriptionLabel: UILabel! {
    didSet {
        descriptionLabel.text = "World"
    }
}

@IBOutlet weak var descriptionView: UIStackView! { // sub container view containing titleLabel and descriptionLabel
    didSet {
        descriptionView.isAccessibilityElement = true
        descriptionView.accessibilityLabel = "Hello"
        descriptionView.accessibilityIdentifier = "test_hello"
    }
}

@IBOutlet private weak var requestButton: UIButton! {
    didSet {
        requestButton.isAccessibilityElement = true
        requestButton.accessibilityLabel = "Request Button"
        requestButton.accessibilityIdentifier = "test_button"
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    dataDisclosureView.isAccessibilityElement = false
    dataDisclosureView.accessibilityElements = [ descriptionView ?? "" ]
    if #available(iOS 17.0, *) {
        dataDisclosureView.automationElements = [ descriptionView ?? "",
                                                  requestButton ?? ""]
    } else {
        // Fallback on earlier versions
    }
   let requestButtonAction = UIAccessibilityCustomAction(name: "start",
                                                      target: self,
                                                      selector: #selector( request))
dataDisclosureView.accessibilityCustomActions = [ requestButtonAction ]
}

需求与问题

需求

  • 为descriptionLabel、titleLabel、requestButton和hintLabel设置accessibilityIdentifier,支持自动化测试
  • 为descriptionView和requestButton设置accessibilityLabel,供VoiceOver无障碍访问

问题

Accessibility Inspector中无法看到Button、TitleLabel及descriptionLabel的accessibilityIdentifier

已尝试的可行方案(不符合WWDC思路)

dataDisclosureView.accessibilityElements = [dataDisclosureView as Any,
                                           titleLabel as Any,
                                           descriptionLabel as Any,
                                           requestButton as Any,
                                           hintLabel as Any]
if #available(iOS 17.0, *) {
    dataDisclosureView.automationElements =  [titleLabel as Any,
                                     descriptionLabel as Any,
                                     requestButton as Any,
                                     hintLabel as Any]
} else {
    // Fallback on earlier versions
}

符合WWDC思路的正确实现

按照WWDC提出的规则:

  • 元素无需被VoiceOver识别 → 不加入accessibilityElements
  • 元素仅需供自动化测试使用 → 仅加入automationElements(iOS17+)

步骤1:为所有需要自动化的元素设置accessibilityIdentifier

先在各元素的didSet中补充accessibilityIdentifier配置:

@IBOutlet private weak var titleLabel: UILabel! {
    didSet {
        titleLabel.text = "Hello"
        titleLabel.accessibilityIdentifier = "test_title" // 新增
    }
}

@IBOutlet private weak var descriptionLabel: UILabel! {
    didSet {
        descriptionLabel.text = "World"
        descriptionLabel.accessibilityIdentifier = "test_description" // 新增
    }
}

// 假设hintLabel的IBOutlet配置如下
@IBOutlet private weak var hintLabel: UILabel! {
    didSet {
        hintLabel.accessibilityIdentifier = "test_hint" // 新增
    }
}

步骤2:修正容器视图的无障碍与自动化配置

override func viewDidLoad() {
    super.viewDidLoad()
    
    // 主容器不作为独立无障碍元素
    dataDisclosureView.isAccessibilityElement = false
    
    // VoiceOver需要识别的元素:descriptionView、requestButton
    dataDisclosureView.accessibilityElements = [descriptionView, requestButton].compactMap { $0 }
    
    // iOS17+ 自动化专用元素:仅需自动化识别的titleLabel、descriptionLabel、hintLabel,可包含VoiceOver元素(自动化也能识别)
    if #available(iOS 17.0, *) {
        dataDisclosureView.automationElements = [
            titleLabel,
            descriptionLabel,
            requestButton,
            hintLabel
        ].compactMap { $0 }
    }
    
    // 保留自定义无障碍动作(如果业务需要)
    let requestButtonAction = UIAccessibilityCustomAction(name: "start", target: self, selector: #selector(request))
    dataDisclosureView.accessibilityCustomActions = [requestButtonAction]
}

关键修正说明

  1. 父容器accessibilityElements的优先级:当父容器设置了accessibilityElements数组后,子元素的isAccessibilityElement=true会被忽略,必须将需要VoiceOver识别的元素显式加入数组。之前的代码未将requestButton加入,导致其无法被VoiceOver识别,也影响自动化识别。
  2. 自动化元素的独立配置:iOS17+的automationElements可以单独配置仅供测试识别的元素,无需将它们加入accessibilityElements(避免被VoiceOver识别)。
  3. 避免无效元素混入数组:用compactMap { $0 }替代?? "",确保数组中只包含有效UI元素,避免类型错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 03:02:18