如何为UICollectionViewListCell的accessory设置accessibilityIdentifier?
问题
在自动化测试中需要通过UIView的accessibilityIdentifier字段触发单元格的展开/折叠操作,但使用UICellAccessory.OutlineDisclosure时,对应的OutlineDisclosureOptions没有提供配置accessibilityIdentifier的选项。当前设置单元格accessory的代码如下:
func headerCellRegistration() -> UICollectionView.CellRegistration<MyCollectionViewListCell, MyStruct> { UICollectionView.CellRegistration<MyCollectionViewListCell, MyStruct>( cellNib: MyCollectionViewListCell.nib(MyCollectionViewListCell.self) ) { cell, indexPath, headerItem in let headerDisclosureOption = UICellAccessory.OutlineDisclosureOptions( style: .header, tintColor: .systemGray) cell.accessories = [ .outlineDisclosure(displayed: .whenNotEditing, options: headerDisclosureOption), ] } }
其中MyCollectionViewListCell是UICollectionViewListCell的子类,请问这种情况下有哪些解决办法?
可行的解决办法
1. 遍历单元格子视图为Disclosure按钮设置标识
系统的OutlineDisclosure本质是一个可交互的按钮视图,我们可以在单元格配置完成后,遍历其视图层级找到该按钮并设置accessibilityIdentifier。建议在配置闭包中延迟执行(确保accessory已添加到视图):
// 在单元格配置闭包内添加 DispatchQueue.main.async { // 递归遍历子视图查找Disclosure按钮 func findDisclosureButton(in view: UIView) -> UIView? { // 可根据实际accessibilityLabel或控件类型匹配,不同iOS版本可能有差异 if view.accessibilityLabel == "Disclosure Indicator" || view is UIControl { return view } for subview in view.subviews { if let button = findDisclosureButton(in: subview) { return button } } return nil } if let disclosureButton = findDisclosureButton(in: cell) { disclosureButton.accessibilityIdentifier = "header_disclosure_\(indexPath.section)" } }
2. 自定义UICellAccessory替换系统控件
创建一个自定义的UICellAccessory,内部包含带accessibilityIdentifier的按钮,模拟系统OutlineDisclosure的样式和行为:
class CustomOutlineDisclosureAccessory: UICellAccessory { private let button = UIButton(type: .system) var tapHandler: (() -> Void)? var accessibilityID: String? { didSet { button.accessibilityIdentifier = accessibilityID } } override init() { super.init() setupButton() } required init?(coder: NSCoder) { super.init(coder: coder) setupButton() } private func setupButton() { // 模拟系统Disclosure图标 let image = UIImage(systemName: "chevron.right") button.setImage(image, for: .normal) button.tintColor = .systemGray button.addTarget(self, action: #selector(onButtonTap), for: .touchUpInside) } @objc private func onButtonTap() { tapHandler?() } override func makeContentView() -> UIView { return button } }
在单元格配置中使用自定义accessory:
func headerCellRegistration() -> UICollectionView.CellRegistration<MyCollectionViewListCell, MyStruct> { UICollectionView.CellRegistration<MyCollectionViewListCell, MyStruct>( cellNib: MyCollectionViewListCell.nib(MyCollectionViewListCell.self) ) { cell, indexPath, headerItem in let customDisclosure = CustomOutlineDisclosureAccessory() customDisclosure.accessibilityID = "header_disclosure_\(indexPath.section)" customDisclosure.tapHandler = { // 绑定展开/折叠逻辑,比如更新Diffable数据源 guard let collectionView = cell.superview as? UICollectionView, let dataSource = collectionView.dataSource as? UICollectionViewDiffableDataSource<Section, Item> else { return } var snapshot = dataSource.snapshot() snapshot.toggleExpansion(of: headerItem) dataSource.apply(snapshot, animatingDifferences: true) } cell.accessories = [customDisclosure] } }
3. 为整个单元格设置标识,通过点击单元格触发操作
如果点击单元格本身会触发展开/折叠(部分列表配置下默认支持),可以直接为单元格设置accessibilityIdentifier,在自动化测试中点击整个单元格即可:
// 在单元格配置闭包内添加 cell.accessibilityIdentifier = "header_cell_\(indexPath.section)"
这种方式需要确认单元格的点击事件已绑定展开/折叠逻辑,等同于点击Disclosure按钮的效果。
内容的提问来源于stack exchange,提问作者Silis Alin
相关产品推荐
相关产品推荐

