UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Checklist: How to make your iOS app more accessible

Quick and easy accessibility changes you can make today

Paul Hudson       @twostraws

Making your app accessible might not make much difference to you personally, but it can and will make a world of difference to many users around the world.

I’ve been attending various talks on iOS accessibility recently. One of them was by Hung Truong from Lyft, and he was asked a question: “I’m trying to convince my boss we should add accessibility – do you have any statistics you can share?”

I loved Hung’s response: “adding accessibility isn’t about making more money, although that might happen. Adding accessibility is about your company culture, and what you actually value.”

So, I’m not going to try to convince you to add VoiceOver – hopefully you’ve already seen just how important it is. Instead, I want to give you a 10-minute check up that you can run on your current projects to get an idea of how accessible they are, along with some advice on how to improve.

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Ten-minute check up

Let’s start with VoiceOver. Although it’s only one of many accessibility features inside iOS, VoiceOver is easily one of the most important because it helps such a wide range of users. Even better, it acts as a fast and easy way to audit your accessibility because you’ll find you can select things that ought to be unselectable, and you’ll often even hear jumbled text as VoiceOver tries to make sense of your UI.

Start by enabling VoiceOver in the Settings app, under General > Accessibility. If you haven’t used VoiceOver before, you can scroll around using three-finger swipes, select elements by tapping on them, and activate controls by double tapping.

  • Make sure all elements have accessibility labels. These can be set in Interface Builder or by using the accessibilityLabel property.
  • Your labels should as short as you can make them, ideally one word. You don’t need to add “Button” or “Slider” because iOS will automatically add that for you.
  • If you don’t provide an accessibility label for images, VoiceOver will use whatever name you gave your image filenames. Yes, this can be embarrassing if you didn’t name your images sensibly.
  • You can also add accessibility hints that are read out after the label. These are designed for first-time users who need more information, but some folks recommend using them only when necessary to avoid too much noise. You can set these in IB or using the accessibilityHint property.
  • Your hints should start with a third-person singular verb that completes the sentence “this button…” or “this control…”. For example “Adds a song to your playlist.” Ending with a full stop or period helps VoiceOver read the hint more naturally.
  • If you localize your app, make sure you localize your accessibility labels and hints.
  • The accessibilityTraits property (exposed as a series of checkboxes in IB) lets you describe what functionality your components do – if they are they buttons, links, or images, and so on.
  • For example, Using UIAccessibilityTraitButton will have VoiceOver say “button” after your label, telling folks it will trigger an action. You might find this useful for your table view cells if they trigger actions: cell.accessibilityTraits |= UIAccessibilityTraitButton does just that.
  • By default iOS will group some things together into a single selection. For example, table view cells with multiple labels and images are selectable as one group, and all get read together.
  • If you prefer to have individual items selected, use cell.isAccessibilityElement = false then cell.contentView.subviews.forEach { $0.isAccessibilityElement = true }. Be warned, though: splitting cells up in this way can cause a lot more screen reading and really slow users down.

 

Next let’s look at how you size things:

  • Dynamic Type will cause your app’s text to grow larger and smaller according to the user’s global settings. You can learn how to make text resize with Dynamic Type here.
  • The least you need to do is use the preferredFont(forTextStyle:) method of UIFont when choosing your fonts. For example, using .headline will give you a larger, bolder font.
  • You should set the adjustsFontForCategorySizeCategory property to true for any labels that use Dynamic Type. This may already be enabled for you, but there’s no harm being sure.
  • If you use IB to configure your fonts, change from the default “System 17.0” to the Body text style.
  • Note: IB does have an option marked “Automatically adjust font” for Dynamic Type, but this won’t affect any custom fonts you use.
  • If you want to use a custom font, make sure you use UIFontMetrics to scale it up. You can read more here, but really it’s just a matter of creating a font metrics object using something like UIFontMetrics(forTextStyle: .headline) then running fontMetrics.scaledFont(for: font) to get back a scaled UIFont.
  • Some users enable larger accessibility sizes, which lets Dynamic Type scale your interface much larger – it’s a smart idea to test your app design by scaling that all the way up.
  • When this option is enabled you can long press on any tab bar item to see a zoomed-up view of its icon and text. This is because tab bar text doesn’t scale well, so it helps folks figure out what each tab does.
  • However, if you use bitmap graphics for your icons you might find they don’t scale up well. To fix this, add icons to your graphics as PDFs, then check the Preserve Vector Data box to have the vector data stored in your app bundle. This will ensure your zoomed icons are drawn smoothly.
  • The absolute minimum size of any tappable component should be 44x44 points. Apple has been saying this since day one, but many folks thought that was too big and went smaller – only to find that it excluded a variety of users. Worse, when iPad Mini came out it made their interfaces unusable for everyone.
  • Apple won’t enforce this rule for you, so consider adding Auto Layout width and height constraints forcing at least 44 points in both directions.

 

Moving on, let’s look at how you arrange things:

  • If you’re showing a custom modal view, VoiceOver might still allow users to select and activate controls behind it. To stop that happening, set your modal view’s accessibilityViewIsModal property to true.
  • Standard hierarchy components like UITabBarController and UINavigationController work great with accessibility out of the box – the system does a great job of helping users navigate through controls in a natural way. So, if for some reason you’re using a hamburger menu or some other custom hierarchy, consider revising that.
  • If you present any kind of modal view that users will dismiss when they are ready, make sure you support the escape gesture. This is available to everyone with VoiceOver enabled, and is triggered by drawing a Z shape with two fingers.
  • Navigation controllers support the escape gesture automatically, but if you present your own view controller you should make it override the accessibilityPerformEscape() method and dismiss itself there.
  • A second gesture enabled by VoiceOver is called the magic tap, which is triggered by a two-finger tap on the screen. You can respond to these with whatever behavior you like: ending a phone call or pausing audio, for example.
  • To support this, override accessibilityPerformMagicTap() in your view controller, then make it do whatever action you think best.
  • When you’re layering content, keep in mind that many users request reduced transparency or reduced motion effects. You should honor this choice by calling UIAccessibilityIsReduceTransparencyEnabled() or UIAccessibilityIsReduceMotionEnabled() respectively – both return true or false depending on the setting, allowing you to take appropriate action.

 

Finally, some quick tips:

  • UIKit does a great job of being accessible by default. So, UILabel, UIButton, UISlider and such are all highly accessible out of the box – they work like users are used to from other iOS apps.
  • If you subclass UIView yourself it’s harder. Make sure you set isAccessibilityElement to true if you’ve made it accessible, and consider setting its accessibilityValue property to something meaningful that VoiceOver can read. This might be something unique, or might be a summary of values from inside it.
  • VoiceOver reads what it sees on the screen by default, but until you actually use it you might not realize what that means. For example, Tweetbot shows “8m” on screen, but reads out “8 minutes ago” with VoiceOver.
  • Make sure you keep your VoiceOver labels and hints up to date as your UI changes. It’s great to add them, but if you change your UI without updating the accessibility text it might do more harm than good.
  • Xcode comes with an accessibility inspector that lets you quickly browse through your app’s accessibility configuration. Activate it by going to Developer tools > Accessibility Inspector, then selecting your simulator. Once it’s active, go to the Inspection menu and choose Enable Point To Inspect – this lets you move your mouse around your iOS app to see how each component looks to the accessibility system.
  • Last but not least, don’t be afraid to make custom user interface for VoiceOver. You can check whether VoiceOver is running by calling UIAccessibilityIsVoiceOverRunning(), and show different UI as needed. For example, if you write an email app that pops up a small “Message sent” label then hides it after a couple of seconds, that will work badly with VoiceOver.

If you’d like to learn more about accessibility (and I hope you do!), I can recommend two excellent talks. The first is from Sommer Panage and is called Accessibility for Users, Designers, and Developers, and the second is from Sally Shepard and is called Beyond VoiceOver – both cover a variety of other ways to help identify and resolve accessibility in your apps.

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

BUY OUR BOOKS
Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

Average rating: 4.5/5

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.