Improving your App’s Accessibility with iOS 13

Wed, May 13, 2020 8-minute read

Note: This article was originally published in Medium

I know, iOS 13 has been with us for quite some time now, WWDC 2020 is just around the corner and we hope Apple will present again a ton of new accessibility features and improvements coming with iOS 14.

But it is almost Global Accessibility Awareness Day! And it is still a great time to catch up and implement everything new that was presented around accessibility in iOS 13 - it was a packed year! - so you are even readier to adapt your apps and fully embrace iOS 14. So I just thought it is a great moment to quickly remember all we can do to improve our app’s accessibility with iOS 13.

Platforms State of the Union

We all know how much Apple cares about accessibility. Last year it was packed of new features, and accessibility was one of the core topics they covered in the Platforms State of the Union session.

Platforms State of the Union (WWDC19). Apple talked about Accessibility, Privacy, Machine Learning, Siri, Augmented Reality, and Metal.

The first thing they talked about was Discoverability. Apple really wants everyone to use any of their devices right out of the box, so they made possible to configure your accessibility preferences on iOS’ Quick Start onboarding process. And they also moved Accessibility to the top level of Settings so it gives it visibility and it makes it easier to find.

But star of the show was Voice Control. Apple presented this new mechanism that lets you use your device with a series of voice commands. You’ll probably think immediately what is new about it if we have Siri already. But Voice Control is a more generic tool that lets you completely interact with any part of the system and with any app you have installed. And more importantly, it runs fully on-device, so it will work even if you are offline.

Navigating the Spotify Player with Voice Control using Names (left), Numbers (centre) or a Grid (right).

You can refer to items in the screen by name, by number, or you can use a grid-based layout for finer control. You can edit text, you can speak gestures… It uses the camera to check if you are speaking to the device or if you are looking somewhere else. It works like magic!

If your app supports VoiceOver well, chances are that it will already be pretty good with Voice Control. But we are not happy with “pretty good”, we want it to be excellent, so we’ll see how you can improve your app’s experience with Voice Control in a minute.

What’s new?!

Voice Control

A great thing I quickly realised about Voice Control is that it is a great way for testing your apps for accessibility. Open your app, go to a screen you want to test and say “Show names”. Voice Control will overlay all the accessibility labels you’ve configured. A quick way to check if they make sense or if there are any missing.

What can you do to further support Voice Control? If your app is accessible, you’ll see that it already works quite well. But the accessibility labels you’ve configured might not be the best for Voice Control. This can be because you may want them to be shorter and easier to say. Or, to make it a bit more intuitive, you may want to provide different alternatives of what the user can say so they don’t have to remember a specific label.

For this, you can provide an array of alternative input labels like this:

// Provide input alternatives for Voice Control
settingsButton.accessibilityUserInputLabels = ["settings", "configuration", "cog"]

This also comes handy for cells in table and collection views where accessibility labels are pretty descriptive. And that is ok, but you may want to provide a more concise label to select them. For example, a banking app may show the merchant, amount, and date for each transaction. A good accessibility label describes all that information. But for easily selecting one transaction with Voice Control, you can provide an accessibility user input label that could be just the merchant.

Apple documentation: https://developer.apple.com/documentation/objectivec/nsobject/3197989-accessibilityuserinputlabels

Large Content Viewer

In iOS 11 Apple introduced Large Content Viewer. When using Larger Accessibility Text Sizes, even if an app supports Dynamic Type, the size of the content in navigation bars and tab bars will not grow. That would take too much real estate from the screen. But if you hold your finger on those elements, a large preview will show in the middle of the screen. This used to only work for iOS native components. But now, iOS 13 lets you implement this for your custom components too.

You can support it by adding a Large Content Viewer Interaction to your custom view, and setting the property showLargeContentViewer to true to the elements within your custom view that you can select and want to provide the preview option to.

Assuming customBarView is your custom view that contains a button called customBarTabButton and another custom view called customBarTabView, as subviews, the code would look something like this:

// Create a Large Content Viewer Interaction
let largeContentViewerInteraction = UILargeContentViewerInteraction()

// Add it to your view
customBarView.addInteraction(largeContentViewerInteraction)

// Enable Large Content Viewer in the buttons or labels you want
customBarTabButton.showsLargeContentViewer = true

// If it is a custom view that you want to enable for Large Content Viewer,
// you can provide an image and title
customBarTabView.showsLargeContentViewer = true
customBarTabView.largeContentImage = UIImage(systemName: "play.circle")
customBarTabView.largeContentTitle = "Play"

If you configure the Large Content Viewer for a button, the image and title of the icon will automatically be used to preview the element. If it is a label, the title will be used too. If it is a custom view, you can configure both the large content image and the large content title.

Example of how Large Content Viewer looks when holding your finger on the Apps tab, in the tab bar of the App Store app, if using Accessibility Text Sizes.

Apple documentation: https://developer.apple.com/documentation/uikit/uilargecontentviewerinteraction

Differentiate Without Color

You should not rely just in colors to signal something in your app. There are users that may not be able to notice differences in the colors you are using and you should accompany this with proper messaging too, for example. But if you really need to - that can probably happen with some games - you can now use this new option in iOS 13.

// Check if the user needs differentiation without color
if UIAccessibility.shouldDifferentiateWithoutColor {
  card.colorSymbolImageView.hidden = false
} else {
  card.colorSymbolImageView.hidden = true
}

Imagine you are developing an UNO-like game where each card has numbers and colors, and the next player chooses its card based on the number or color of the previous player’s card. You could check if the user has enabled the Differentiate Without Color option and show an extra symbol in the card that represents the color. Actually UNO has a color-blind friendly version, UNO ColorADD, that uses the Colorblind Alphabet.

UNO Colorblind Cards. UNO® ColorADD

Apple documentation: https://developer.apple.com/documentation/uikit/uiaccessibility/3043553-shoulddifferentiatewithoutcolor

Auto-Play Video Previews

In a similar way, a user can now decide to disable auto-play for video previews. You should always try to honor the user’s preferences.

// Check if the user has Video Autoplay enabled
if UIAccessibility.isVideoAutoplayEnabled {
  video.play()
} else {
  video.pause()
}

Apple documentation: https://developer.apple.com/documentation/uikit/uiaccessibility/3238036-isvideoautoplayenabled

Note: For both Differentiate Without Color and Auto-Play Video Previews, you can listen to their corresponding ‘did change’ notifications.

Custom Actions with action handlers

You can add custom actions to views. This improves navigation with VoiceOver and Switch Control. A common use case is when a cell in a table view has multiple buttons that let you execute multiple actions. It used to be that you had to provide the name of the action, and also a target and selector, for each one of these custom actions. In iOS 13, Apple introduced a Swiftier way of doing it where you can just provide a closure (instead of the target and action) with the code that will be executed when you trigger the custom action.

// Create Custom Actions
let artistCustomAction = UIAccessibilityCustomAction(name: userName) { _ in
  self.navigationController?.present(artistViewController, animated: true, completion: nil)
  return true
}

let likeCustomAction = UIAccessibilityCustomAction(name: "like") { _ in
  likedSongs.append(song)
  return true
}

// Add Custom Actions to your view
accessibilityCustomActions?.append(contentsOf: [artistCustomAction, likeCustomAction])

Apple documentation: https://developer.apple.com/documentation/uikit/uiaccessibilitycustomaction/3043557-init

Environment Overrides & Accessibility Inspector

Testing your iOS apps for accessibility became much easier too.

The Accessibility Inspector added a preview option for VoiceOver. Just click on the speaker button and use the player controls to play/pause or go to the previous/next element.

The Accessibility Inspector can now offer a Quicklook to preview VoiceOver in the simulator.

And Xcode added a Environment Overrides menu that lets you customize a ton of options when running the app in the simulator, including some accessibility configurations like: Increase Contrast, Reduce Transparency, Reduce Motion, Smart Invert, Differentiate Without Color, and many more.

Environment Overrides lets you customise a bunch of user preferences in the simulator.

SwiftUI

Of course, SwiftUI was also presented in the WWDC19. Like everything that Apple does, accessibility is built-in right from the beginning. For sure you’ve noticed already that a lot of things in iOS are accessible by default. But this is even more true with SwiftUI thanks of its declarative nature and because it is state-driven. This probably deserves its own post, or even series of posts, so I totally recommend you Rob Whitaker’s great SwiftUI Accessibility Series: https://rwapp.co.uk/2019/11/06/SwiftUI-Accessibility/

And there is more…

As I said, it was one of the WWDC editions that I remember with more news around accessibility. Apart from all the ones in this post, Apple also presented Full Keyboard Access for iPadOS, SF Symbols (making easier to support dynamic type with glyphs), when using color asset catalogues you can specify high contrast variants, etc.

Have I missed anything? Please let me know in the comments. And if you have any feedback, questions, etc, you can also find me on Twitter: @dadederk Let’s now hope for another WWDC full of accessibility improvements!

Thanks for reading!

Resources

Developing Accessible iOS Apps by Daniel Devesa Derksen-Staats