Introduction to supporting VoiceOver in SwiftUI
Learn how to use different accessibility modifiers in SwiftUI.
updated on 09 Sep 2024 · 8 min read
Making an app accessible is crucial for ensuring that all users, including those with disabilities, can enjoy a seamless experience. For instance, users who rely on assistive technologies like VoiceOver should be able to interact with our apps without needing to see the screen.
SwiftUI simplifies the process of adding accessibility to our apps by automatically setting accessibility labels and values for standard views like navigation views, lists, text fields, sliders, and buttons. However, there are scenarios where additional work is needed to enhance the user experience, particularly when using custom views, images, or image-only buttons.
Let's dive into a practical example.

Finding VoiceOver issues
The first step in improving accessibility is to identify potential VoiceOver issues. We can do this by either activating VoiceOver on our device or by using Xcode’s Accessibility Inspector.
To open the Accessibility Inspector, select Xcode > Open Developer Tool > Accessibility Inspector in Xcode's menu.
The Accessibility Inspector allows us to navigate through different view elements and listen to how VoiceOver reads them. This helps us assess whether the accessibility values are providing a good user experience.
While the Accessibility Inspector is a useful development tool, it doesn’t replace the need to test accessibility features with VoiceOver on an actual device. To learn how to use VoiceOver, check out this guide on VoiceOver gestures for iOS.
Example: Improving accessibility of an image-only button
When using buttons with titles, SwiftUI automatically assigns appropriate accessibility values.
Button("Cancel", action: {// Cancel button action})
In this example, VoiceOver will correctly read Cancel Button to the user, requiring no further action on our part.
However, the situation changes when using image-only buttons. SwiftUI will still recognize the element as a button, but without an appropriate label, VoiceOver will only announce Button which is unhelpful for users who cannot see the image.
To address this, we can use the accessibilityLabel(_:) modifier to provide a descriptive label for the button:
Button("", action: {// Favorites button action}).buttonStyle(ImageButtonStyle(systemImage: "heart")).accessibilityLabel("Favorites")
With this label in place, VoiceOver will now read Favorites Button offering much clearer guidance to the user.
Besides accessibilityLabel(_:), SwiftUI provides other accessibility modifiers to improve accessibility.
Example: Improving accessibility when using onTapGesture
When using onTapGesture in SwiftUI, the view doesn't automatically gain accessibility traits, which can make it invisible to VoiceOver users. To ensure accessibility, we need to add appropriate labels and traits.
Consider an example where an image triggers an action when tapped:
Image(systemName: "heart").onTapGesture {favoriteItem()}
In its current form, VoiceOver users won't know this image is interactive. We can improve accessibility by adding a label and traits:
Image(systemName: "star").onTapGesture {favoriteItem()}.accessibilityLabel("Favorite").accessibilityAddTraits(.isButton)
Example: Improving accessibility by combining views to one accessibility element
Sometimes, multiple views on the screen represent a single piece of information or an action. For example, a label and an icon together might indicate the same function. By default, VoiceOver will read each view separately, which can be confusing. To improve accessibility, we can combine these views into one accessibility element.
Consider this example with a text label and an image:
HStack {Image(systemName: "heart")Text("Favorite")}
By default, VoiceOver will read "Star" and "Favorite" separately. We can improve this by combining them into a single accessible element:
HStack {Image(systemName: "star")Text("Favorite")}.accessibilityElement(children: .combine).accessibilityLabel("Favorite")
Commonly used accessibility modifiers
To summarize, here is a list of the commonly used accessibility modifiers:
- accessibilityLabel(_:) to describe the contents of a view.
- accessibilityValue(_:) to describe the value that the view contains, if it is different from the view's accessibility label.
- accessibilityHint(_:) to describe what happens after performing the view’s action.
- accessibilityAction(_:_:) to add a custom accessibility action to the view.
- accessibilityAddTraits(_:) to add a trait like .isButton or .isSearchField to the view.
- accessibilityRemoveTraits(_:) to remove a trait from the view.
- accessibilityHidden(_:) to specify whether to hide the view from accessibility features.
- accessibilityElement(children:) to create a new accessibility element and influence its child views behaviour, for example to combine multiple views into one accessibility element.



Newsletter
Like to support my work?
Say hi
Related tags
Articles with related topics
Latest articles and tips



