iOS 16下UITableViewCell无障碍API失效,导致XCTest中断
iOS 16 下自定义 UITableViewCellConfiguration 无障碍属性失效问题解决办法
升级至iOS 16后,自定义CellConfiguration及CellContent中设置的isAccessibilityElement、accessibilityLabel等无障碍属性会完全失效,模拟器与真机均无法检测到对应单元格的无障碍元素。该功能在iOS 16之前正常可用,目前已导致现有XCTest用例中断,阻碍无障碍应用开发进度。
问题原因
iOS 16对UITableViewCell的无障碍处理逻辑做了调整:
- 当使用
contentConfiguration时,系统默认将单元格本身(UITableViewCell)作为无障碍元素,会忽略其内部contentView子视图的无障碍设置; CellContent作为contentView的子视图,其无障碍属性会被单元格的容器层级覆盖,无法被无障碍检测工具识别。
解决方案
针对这个问题,有两种可行的解决思路:
思路1:直接在UITableViewCell层面配置无障碍属性
放弃在CellContent中设置无障碍属性,转而直接在单元格实例上配置,让系统将整个单元格识别为一个无障碍元素:
修改后的单元格创建代码:
private func createCell(in tableView: UITableView) -> UITableViewCell? { guard let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier") else { return nil } cell.contentConfiguration = CellConfiguration() cell.selectionStyle = .none // 直接在cell上设置无障碍属性 cell.isAccessibilityElement = true cell.accessibilityLabel = "I'm a label" cell.accessibilityValue = "I'm a value" cell.accessibilityTraits = [.header] cell.accessibilityIdentifier = "cellID" return cell }
思路2:保留CellContent的无障碍设置,调整单元格的无障碍层级
如果需要让CellContent作为独立的无障碍元素,需要禁用单元格本身的无障碍标识,确保内部视图的无障碍属性能被识别:
- 先修改
CellConfiguration,添加无障碍配置参数(用于传递给CellContent):
public struct CellConfiguration: UIContentConfiguration { // 新增无障碍相关配置属性 let accessibilityLabel: String let accessibilityValue: String let accessibilityTraits: UIAccessibilityTraits let accessibilityIdentifier: String public func makeContentView() -> UIView & UIContentView { CellContent(configuration: self) } public func updated(for state: UIConfigurationState) -> CellConfiguration { self } }
- 修改
CellContent,在配置更新时设置无障碍属性:
private class CellContent: UIView, UIContentView { var configuration: UIContentConfiguration { didSet { guard let config = configuration as? CellConfiguration else { return } isAccessibilityElement = true accessibilityLabel = config.accessibilityLabel accessibilityValue = config.accessibilityValue accessibilityTraits = config.accessibilityTraits accessibilityIdentifier = config.accessibilityIdentifier } } init(configuration: UIContentConfiguration) { self.configuration = configuration super.init(frame: .zero) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
- 最后修改单元格创建代码,禁用单元格本身的无障碍标识:
private func createCell(in tableView: UITableView) -> UITableViewCell? { guard let cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier") else { return nil } // 初始化配置时传入无障碍参数 let cellConfig = CellConfiguration( accessibilityLabel: "I'm a label", accessibilityValue: "I'm a value", accessibilityTraits: [.header], accessibilityIdentifier: "cellID" ) cell.contentConfiguration = cellConfig cell.selectionStyle = .none // 关键设置:禁用cell本身的无障碍元素标识 cell.isAccessibilityElement = false cell.contentView.isAccessibilityElement = false return cell }
验证方法
- 使用Xcode的Accessibility Inspector(Xcode菜单 > Open Developer Tool > Accessibility Inspector),在模拟器或真机上检查是否能正确识别目标无障碍元素;
- 重新运行XCTest用例,验证无障碍相关断言是否通过。
内容的提问来源于stack exchange,提问作者Haroun Hajem
相关产品推荐
相关产品推荐

