Article

Supporting VoiceOver in Your App

Learn how to make your iOS app more accessible to users who are blind or have low vision by adding VoiceOver support.

Overview

VoiceOver is a screen reader that enables people to experience the interface on their devices without having to see the screen. People who are blind depend on VoiceOver to provide auditory feedback while using their iOS devices, but VoiceOver is not exclusively for the blind community. For example, someone prone to motion sickness might choose to turn VoiceOver on while they are in a moving vehicle. While VoiceOver assists all types of people, those who are blind rely on VoiceOver whenever they use their devices.

In a few steps you can make your app VoiceOver accessible in Xcode or programmatically. By increasing accessibility, you open your app to a wider audience, and make it easier for everyone to use.

Two iPhones with VoiceOver turned on. The phone on the left has the camera app open and the VoiceOver cursor is highlighting the timer. The phone on the right shows a contact in the phone app for Maria Ruiz. The call home button is highlighted by the VoiceOver cursor.

Audit Your App with VoiceOver On

To test the accessibility of your app, turn on VoiceOver and navigate through the interface. By using your app with VoiceOver on, you can establish a baseline of its accessibility. To start auditing, go to Settings > General > Accessibility > Accessibility Shortcut, and tap to select VoiceOver. Then, open your app and use the specified action for Accessibility Shortcuts whenever you want to test VoiceOver.

Auditing also reveals which elements are accessible with VoiceOver and which aren’t, and shows you if VoiceOver navigation is clear and logical. Keep track of which elements are not accessible and create a list of improvements for adding better VoiceOver support.

Navigate with VoiceOver On

To audit your app with VoiceOver on, you'll use VoiceOver's unique set of gestures to navigate your app. For testing, there are five key gestures that you may use:

  • Swipe left or right to navigate to the next or previous UI element.

  • One-finger double-tap to activate the selected element.

  • Two-finger tap to stop and resume speaking.

  • Swipe up with two fingers to read everything onscreen.

  • Three-finger triple-tap to turn screen curtain on and off.

To learn more, see Learn VoiceOver gestures in the iPhone User Guide.

To replicate the experience of someone who is solely relying on VoiceOver, test your app using screen curtain. As the name implies, screen curtain blacks out the entire screen. You can still navigate using VoiceOver gestures, but you can’t see the elements on the screen.

Now that you can turn VoiceOver on and know how to navigate though your app, you are ready to start testing your app.

Identify Common Accessibility Issues

To audit your app, check that you can access every element and that the ordering of those elements is what you intended. Take note of which elements VoiceOver can or cannot access. Also, pay attention when you find it difficult to perform a task because you assume it is reliant on visuals. For example, when you are navigating back to your app’s initial view, or you are sharing content with another app or user, how can you use VoiceOver to make it accessible? While auditing your app, here are some common issues to look out for:

  • Add accessibility information for your app's elements. VoiceOver doesn’t recognize custom UI elements by default. You need to add additional accessibility information to these elements.

  • Group elements so that VoiceOver navigates through them in the correct order. VoiceOver reads from the leading to the trailing edge. If you want VoiceOver to read your elements in a different order, use groups to facilitate navigation that makes sense for your app.

  • Include descriptive text for VoiceOver to read. A UI that depends on visual cues may look nice, but can be unusable for a VoiceOver user. For example, VoiceOver doesn't detect if a confirmation button turns from gray to green when selected. VoiceOver may only describe the element and not it’s current state. Make sure that VoiceOver says whether you have selected the button.

Once you know which areas need improvements, start adding greater VoiceOver support to your app.

Update Your App’s Accessibility

For elements that were not accessible to VoiceOver, start by improving their accessibility labels and hints:

  • The accessibilityLabel property provides descriptive text that VoiceOver reads when the user selects an element.

  • The accessibilityHint property provides additional context (or actions) for the selected element.

Accessibility labels are very important, because they provide the text that VoiceOver reads. A good accessibility label should be short and informative. It is important to note that a UILabel and an accessibilityLabel are different things. By default, VoiceOver reads the text associated with standard UIKit controls such as UILabel and UIButton. However these controls can also have corresponding accessibilityLabel properties to add more detail about the label or button..

Depending on the context, hints aren’t always necessary. In some cases, the label provides enough context. If you feel like you’re saying too much in an accessibility label, consider moving that text into a hint.

To ensure that users understand the intent of your interface, you might need to set some accessibility labels manually. Accessibility labels and hints can either be set in Xcode’s Identity Inspector or programmatically.

Add Accessibility Labels and Hints Using the Identity Inspector

When using standard UIKit controls, assign accessibility labels and hints in Xcode using the Identity Inspector’s Accessibility pane. To improve accessibility, you make an element accessible by checking the accessibility checkbox. For example, the play button in a music app might include the label and hint shown in Figure 2.

Figure 3

The Accessibility pane in the Identity Inspector

A screenshot from Xcode, showing the Accessibility pane of the Identity inspector. This pane includes a checkbox to enable accessibility, and three text fields in which you enter text for an object’s Label, Hint, and an Identifier. In this screenshot, the Accessibility checkbox is Enabled. The Label field says “Play song,” and the Hint field says “Play the selected song.” The Identifier field is blank.

Add Accessibility Labels and Hints Programmatically

There are times when adding accessibility labels and hints in Xcode is not enough. For example, when you are working with custom UI elements which are not automatically recognized by VoiceOver or if you are using variables as part of your accessibility labels. In these situations, you need to set the accessibility labels or hints programmatically. You first need to specifiy that an element is an accessibility element and then create a corresponding accessibility label and hint.

To make your element accessible to VoiceOver programmatically, you need to define it as an accessibility element:

score.isAccessibilityElement = true

An element’s label might not stay the same throughout the entire life cycle of your app. For example, a counter for keeping score as you play a game, you want to change the label as the score increases. You can do this by programmatically setting an accessibility label and hint:

score.accessibilityLabel = "score: \(currentScore)"
score.accessibilityHint = "Your current score" 

Simplify Your Accessibility Information

VoiceOver reads in the direction of the language the device is set to. For example, in English-speaking countries, VoiceOver reads from left-to-right, while Arabic and Farsi are read right-to-left. If you vertically stack labels in a UI or display text in a table, VoiceOver may not read the labels in the correct order. You can programmatically group accessibility elements to ensure that VoiceOver reads them as intended. For example, say you are creating an app that stacks a title and a value to display a contact's Name and Email address, as shown in Figure 3. Depending on their order in the interface, VoiceOver may not read those elements together. To ensure that you are creating a clear context, you want to group the elements together.

Figure 2

An example of how VoiceOver navigates with and without grouping

Two side-by-side diagrams, demonstrating how VoiceOver reads ungrouped and grouped labels. On the left, there are two pairs of ungrouped labels—one pair on the left and another pair on the right—used to depict a person’s name and email address. When ungrouped, VoiceOver reads the labels in a top-left, top-right, bottom-left, and bottom-right sequence. On the right, the top- and bottom-left labels are in one group, and the top- and bottom-right labels are in a second group. When grouped, VoiceOver still reads left-to-right and top-to-bottom, but this time it reads the first group (at left) before reading the second group (at right) from top-to-bottom.

On the left, there are four labels that VoiceOver reads from the leading to the trailing edge, in this case left-to-right. While every element is accessible to VoiceOver, this does not provide a great user experience. On the right, VoiceOver reads the grouped labels in the intended order allowing for clear navigation.

To group the labels programmatically, start by create a UIAccessibilityElement, and then add the information you would like to have grouped together. For example, group to combine the labels as follows:

var elements = [UIAccessibilityElement]()
let groupedElement = UIAccessibilityElement(accessibilityContainer: self)
groupedElement.accessibilityLabel = "\(nameTitle.text!), \(nameValue.text!)"
groupedElement.accessibilityFrameInContainerSpace = nameTitle.frame.union(nameValue.frame)
elements.append(groupedElement)

Including an accessibility label for each element and grouping elements allows people who depend on VoiceOver to navigate their devices and use your app.

See Also

First Steps

UIAccessibility

A set of methods that provide accessibility information about views and controls in an app's user interface.

UIAccessibilityContainer

A set of methods that view subclasses use to make subcomponents accessible as separate elements.