SwiftUI is Apple’s new technology for building user interfaces on Apple platforms. Apple have made some very important accessibility choices with SwiftUI that mean accessibility is included by default. Our job as developers is to improve an accessible experience, not to create one.
This series is my guide to all the new accessibility features in SwiftUI and how to leverage them as a developer to create the best experience possible.
Accessibility is important. We can take that as a given. But as iOS devs we’re not always sure how to make the most of the accessibility tools that Apple have provided us.
We’re lucky as iOS developers that we work on such a forward-thinking accessibility platform. Many people consider Apple’s focus on accessibility for iOS as the driver for other technology vendors to include accessibility features as standard. To the point that we now consider accessibility an expected part of any digital platform. This was not the case before 2009.
Semantic views are not new to SwiftUI, but changes in SwiftUI mean creating them is simple. Semantic views are not so much a language feature. They’re more a technique for manipulating the accessible user interface and improving the experience for assistive technology users.
A what view? # A semantic view is not one view, but a collection of views grouped together because they have meaning (or semantic) together. Take a look at this iOS table view cell from the files app.
SwiftUI allows us to read environmental values that might affect how we want to present our UI. Things like size classes and locale for example. We also get the ability to read some of the user’s chosen accessibility settings allowing us to make decisions that will best fit with your customer’s preference.
Why? # Before we cover what these options are and how to detect them I think it’s important to briefly cover why we need to detect them. There’s a few dos and don’ts worth consideration.
Accessibility traits are a group of attributes on a SwiftUI element. They inform assistive technologies how to interact with the element or present it to your customer. Each element has a selection of default traits, but you might need to change these as you create your UI.
In SwiftUI there are two modifiers to use for traits, .accessibility(addTraits: ) and .accessibility(removeTraits: ) which add or remove traits respectively. Each modifier takes as its argument either a single accessibility trait or a set of traits.
When a customer enables an assistive technology to navigate your app the interface that technology navigates isn’t exactly the same as the one visible on the screen. They’re navigating a modified version that iOS creates especially for assistive technology. This is known as the accessibility tree or accessible user interface.
iOS does an incredible job at creating the AUI for you from your SwiftUI code. We can help iOS in creating this by tweaking some element’s accessibility attributes. Setting some accessibility attributes through modifiers is a simple way to add a little more meaning and context for your assistive technology users.
Take a look at your app. Notice the collection of buttons, text, images, and other controls you can see and interact with that make up your app’s user interface. When one of your customers navigates your app with Voice Control, Switch Control, VoiceOver, or any other assistive technology, this isn’t the interface they’re using. Instead, iOS creates a version of your interface for assistive technology to use. This interface is generally known as the accessibility tree. Apple often refers to this as your app’s Accessible User Interface. For brevity and consistency in this article, I’ll refer to it as the AUI
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.
One big accessibility improvement in SwiftUI comes in the form of named controls. Nearly all controls and some non-interactive views (see Images) can take a Text view as part of their view builder. The purpose of this is to tie the meaning to the control.
Toggle(isOn: $updates) { Text("Send me updates") } Imagine a UIKit layout with a UISwitch control. We’d most likely right align the switch, and provide a text label to the left. Something like this.
Like all accessibility features, Dynamic Type is about customisability. Many of your customers, and maybe even you, are using Dynamic Type without even considering it an accessibility feature. Dynamic type allows iOS users to set the text to a size that they find comfortable to read. This may mean making it a little larger so it’s easier to read for those of us who haven’t yet accepted we might need glasses. Or it could mean ramping it right up for people with low vision. Or taking the text size down for extra content and privacy. Like many accessibility features on iOS, Dynamic Type support has been greatly improved in SwiftUI. There are a few things you should do (and not do) to make the most of it.
Images in SwiftUI are accessible by default. This is the opposite of what we’d experience in UIKit, where images are not accessible unless you set isAccessibilityElement to true.
Sometimes making images not accessible to VoiceOver is the right decision. Like when using a glyph as a redundant way of conveying meaning alongside text. An example of this would be displaying a warning triangle next to the text ‘Error’ or a tick next to ‘success’. If these images were accessible your VoiceOver users would hear the word ‘error’ twice and have to swipe between each one. This makes navigation longer and frustrating for your customer.