Building Accessible iOS Apps

How to Avoid Common Accessibility Issues in iOS apps

Rob Whitaker
Capital One Tech

--

hand holding phone with teal screen, against blue background with various phone icons

Accessibility is usability.

Accessibility isn’t just about making our apps work for people with disabilities, but allowing all our customers to experience our apps in the way that is most comfortable for them. Ensuring all your app’s content is included in a scroll view means we can guarantee the content can be accessed, regardless of the size of your customer’s screen. But this also means your content can be dynamic without worrying if it will still fit, and allows the content to scale. This is just one example, but adding features such as entering text by voice or adding captions to videos have similar universal benefits.

Below I’ve collected some common accessibility issues I’ve seen with iOS code, and some quick pointers for avoiding some common accessibility mistakes for iOS apps. These won’t solve for every one of your customers, but they’ll go a long way to improving your app’s experience. Once you’ve implemented these, be sure to test them. And if you can, I would recommend doing user testing with people with a range of abilities. I’ve included some quick tips for developer testing at the end of this blog.

Building Interfaces

Custom Controls

If you need to customize a control to change the design or add functionality, try to subclass at the highest level possible, this keeps as much of Apple’s accessibility defaults intact as possible. For example, if your control is a variation on a button, subclass UIButton. If you can’t do what you need with UIButton, subclass UIControl.

Consider making a collection of fundamental controls with a little extra accessibility, then you can subclass these where needed knowing you’ll always have the best accessibility available. For example, UIButton and UILabel are all limited to one line of text by default, this means your customers with larger text sizes or smaller screens might lose some of the text. Set numberOfLines = 0 and adjustsFontForContentSizeCategory = true on your element’s label.

Image Buttons

All image buttons need an accessibilityLabel attribute adding with a short but meaningful title. Ideally keep this to one word, and don’t add the word “button”. Some UINavigationItem buttons will automatically add the correct accessibility label for you, in this case, stick with Apple’s default.

imageButton.accessibilityLabel = “Buy”

Images

Icons generally should be marked as accessibilityHidden as they don’t add any additional meaning. The text they are next to should add all the context needed.

icon.accessibilityHidden = true

black text next to blue checkmark icon

The tick icon above should be hidden from accessibility because the text to the right gives all the information the customer needs.

Larger icons and photos should have an accessibilityLabel to avoid appearing as a large blank space on the screen to VoiceOver users, but the screen’s initial focus should always be the page title. If you find in VoiceOver testing the images takes focus first, you can move focus by using the .layoutChanged notification below after the screen has appeared. This moves VoiceOver focus to the element you pass as an argument. Make sure your accessibility label is short, and in the case of an icon that it describes the meaning of the icon, not the icon itself — eg, a phone icon should be ‘call us’ not ‘phone’.

UIAccessibility.post(notification: .layoutChanged, argument: screenTitle)

large blue checkmark icon above black text and black rectangular button

The tick icon at the top of this screen should have a description of ‘success’. Don’t include words like “image” or “icon” in the label, iOS will do this for us. Ensure the VoiceOver focus when navigating to this screen is the ‘You successfully completed the action!’ title, not the icon.

Reference Numbers

Reference numbers such as phone numbers or order reference numbers etc should be read as individual digits, not as a whole number. We need to tell VoiceOver to do this. You can do this by setting an accessibilityAttributedLabel.

let orderNumber = “1234”
let orderReference = “Order reference \(orderNumber)”
orderReferenceLabel.text = orderReference

let attributedString = NSMutableAttributedString(string: orderReference)
let range = attributedString.string.range(of: orderNumber)
attributedString.addAttributes([.accessibilitySpeechSpellOut: true], range: range)

orderReferenceLabel.accessibilityAttributedLabel = attributedString

Disabled Elements

Disabled elements, generally buttons, are an anti pattern. It is not clear to any user when seeing the button why this button is disabled. As a general rule, try to avoid disabled buttons. Instead, allow the customer to tap the button and provide clear feedback explaining why we can’t allow the customer to continue. In VoiceOver, move the focus to the first errored element on screen. For example, below the first element on screen in an error state is referenced as textField, using the layoutChanged notification we’re telling VoiceOver to focus on that element.

UIAccessibility.post(notification: .layoutChanged, argument: textField)

Scroll Views

If you have text on a screen, and that text is not inside a scroll view somewhere in its hierarchy, that text is not accessible. You can’t guarantee it will appear correctly on a small screen device, and you can’t guarantee it has the room to scale to our customer’s chosen text size.

Testing

As with any software change, you can’t be sure it’s worked unless you test it. Its always worth checking a screen with VoiceOver before moving your ticket. This won’t cover everything, but it’s a good guide that your accessibility is okay.
Load your app onto a device, browse to your screen, then enable VoiceOver and navigate the screen. Can you reach every piece of text and control? Do the labels and navigation order make sense to anyone who can’t see the screen? Does VoiceOver access elements that are hidden? Does VoiceOver access any elements that don’t add meaning to the screen?

Enabling VoiceOver
Hopefully your testing device will already have VoiceOver setup to work with the accessibility shortcut. If so, you can press the sleep/wake button, or home button, 3 times. This will enable VoiceOver, to disable VoiceOver do the same thing again. If nothing happens when you do this set up the accessibility shortcut in Settings > Accessibility > Accessibility Shortcut and select VoiceOver. Do this before continuing, or turning it off will be hard work.
To navigate with VoiceOver swipe to the right to navigate down the page, and to the left to navigate up. To activate a control double tap. There are many more gestures, but this should be enough for some basic testing.

Conclusion

Accessibility is a massive topic, and because it’s so human-centric it’s important to continuously strive to do better. So don’t be afraid to ask and reevaluate if you’re doing the right thing, and prepare to be shown ways you can improve. Using accessibility labels and making sure your interface is robust using some of the techniques I covered here will go a long way towards making your app work better; not just for people with disabilities, but for all of your customers. If you’d like to get into more detail about the sorts of tools you can use on iOS to make your app a better experience for people with different abilities, check out Apple’s Accessibility guide as part of the iOS Human Interface Guidelines. You can also check out my book, Developing Inclusive Mobile Apps: Building Accessible Apps for iOS and Android.

Vector created by anshuor — www.freepik.com

DISCLOSURE STATEMENT: © 2020 Capital One. Opinions are those of the individual author. Unless noted otherwise in this post, Capital One is not affiliated with, nor endorsed by, any of the companies mentioned. All trademarks and other intellectual property used or displayed are property of their respective owners.

--

--

Rob Whitaker
Capital One Tech

iOS Engineer at Capital One. Author, Developing Inclusive Mobile Apps, Apress. https://amzn.to/3aNRQ6d