SwiftUI Accessibility: Sort Priority

Rob Whitaker
Oct 2, 2019 · 3 min read
Image for post
Image for post

Assistive technology, such as VoiceOver, works in natural reading direction. In English, and most other languages, this means top left through to the bottom right. Mostly this is the right decision for assistive technology to make. This is the order anyone not using assistive technology would experience your app. Sometimes though, we make designs that don’t read in this way.

By using the .accessibility(sortPriority: ) modifier we can set the order in which assistive technology accesses elements. To achieve this, you must group elements in a stack (HStack, VStack or ZStack). Then use the .accessibilityElement(children: .contain) modifier. The higher the number we give to .accessibility(sortPriority: ), the earlier VoiceOver will focus on the item. This means an element with a priority of 2 comes before priority 1, and so on.

VStack {   Text(“Read this last”)
.accessibility(sortPriority: 0)
Text(“Read this first”)
.accessibility(sortPriority: 2)
Text(“Read this second”)
.accessibility(sortPriority: 1)
}
.accessibilityElement(children: .contain)
Text highlighted by VoiceOver
Text highlighted by VoiceOver

One example of using this might be captioning a large image. In SwiftUI images are accessible by default. This doesn’t mean we should focus on the image as the first element — the title is usually more meaningful. Here, we’d set the sort priority of the image to 0 so it receives focus after VoiceOver has read the title and caption.

VStack {   Image(“shuttle”)
.accessibility(sortPriority: 0)
Text(“Shuttle”)
.font(.largeTitle)
.accessibility(sortPriority: 2)
Text(“This is an image of a shuttle on the launch pad”)
.accessibility(sortPriority: 1)
}
.accessibilityElement(children: .contain)
Image for post
Image for post

Another use of this could be a custom stepper control. We’d want VoiceOver to focus on the value first to orientate your user and inform them which value they’re starting with. Then VoiceOver should follow with the decrease and increase buttons. We’d achieve this like this:

HStack {   Button(action: {
self.value -= 1
}) {
Text(“Decrease”)
}
.accessibility(sortPriority: 1)
Text(String(value))
.accessibility(sortPriority: 2)
Button(action: {
self.value += 1
}) {
Text(“Increase”)
}
}
.accessibilityElement(children: .contain)
A custom stepper control
A custom stepper control

As of October 2019, the sort priority only works for elements inside a stack where the stack has the modifier of .accessibilityElement(children: .contain). I don’t believe this is intentional, hopefully, future releases of SwiftUI will drop this requirement.

Flawless iOS

🍏 Community around iOS development, mobile design, and…

Rob Whitaker

Written by

iOS Engineer at Capital One. Author, Developing Inclusive Mobile Apps, Apress. https://amzn.to/3aNRQ6d

Flawless iOS

🍏 Community around iOS development, mobile design, and marketing

Rob Whitaker

Written by

iOS Engineer at Capital One. Author, Developing Inclusive Mobile Apps, Apress. https://amzn.to/3aNRQ6d

Flawless iOS

🍏 Community around iOS development, mobile design, and marketing

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store