Can a UIView object combine the accessibility properties of its children automatically?

I have a view hierarchy as follows:

UIView
  \-- UIStackView
    +-- UILabel
    \-- UILabel

By default, VoiceOver skips over the UIView and stops on each of the UILabels separately.

I would like VoiceOver to stop on the UIView and combine its contents (i.e. read the accessibility label of each of its accessible children one by one). Does UIKit offer an API to achieve this similar to SwiftUI's accessibilityElement(children: .combine) API?

Notes

  1. I know I can set isAccessibilityElement to true on the UIView and then set its accessibilityLabel to "\(label1.text!) \(label2.text!)". I'm wondering whether there is an automatic means of achieving this which doesn't require me to define the UIView's accessibilityLabel.
  2. The problem with having to define the UIView's accessibilityLabel manually based on its children is that I have to remember to change the UIView's accessibilityLabel in every place where the text or accessibilityLabel of any of its children changes.

Replies

Hey there, this indeed is one example of the difference in accessibility API implementation between UIKit and SwiftUI. If you'd like to file feedback or suggestions about this, please do so! Check out Feedback Assistant, https://developer.apple.com/bug-reporting/

While you may manually need to code this, you can essentially set up a flow of accessibility API between these views in the direction of subview → parent which should give you the same user experience as using accessibilityElement(children: .combine).

In UIKit, you can access accessibility API on subviews directly, like label.accessibilityLabel from your UIStackView, where the UILabel's accessibilityLabel is populated automatically by UIKit based on its text value. So you can set your UIStackView's accessibilityLabel as a combination of the accessibilityLabels of its subviews (similar to your note 1), then set your UIView's accessibility label to be that of the UIStackView.

This way, you shouldn't need to change anything manually, and your views are passing information along up the hierarchy such that whenever the text value for the labels change, your UIView's accessibility information is updated. If you feel this still doesn't solve your use case, could you share more details about your view hierarchy and how you are setting up these view classes in your project?

  • Thanks for your response. I have submitted a suggestion in Feedback Assistant just now for an API like accessibilityElement(children: .combine) to be added to UIKit. Until that's added, I'm running with your idea of updating the parent view's accessibility label whenever the text in any of the children changes by means of the stack view, as follows: parentView.accessibilityLabel = stackView.arrangedSubviews.map { $0.accessibilityLabel ?? "" }.joined(separator: " ").

Add a Comment