Tips and tricks to build accessible iOS apps

#365DaysIOSAccessibility

A year-long journey exploring iOS accessibility, one day at a time. Each post shares practical insights, tips, and techniques to make your iOS apps more accessible.

Dynamic Type is a feature that lets a user change the font size (smaller or larger) of the whole system or a particular app. To support it, choose a preferred font based on one of the 11 supported text styles: Large title, heading, body...

With accessibilityRepresentation(representation:), you can create a custom component and it can be perceived by assistive technologies as the view you pass as representation. No need to manually configure accessibility attributes. It is one of the most interesting additions to SwiftUI to help you develop accessible UI components. If your custom component behaves similarly to a native one, this is the way to go. https://developer.apple.com/documentation/swiftui/view/accessibilityrepresentation(representation:)

In SwiftUI you won't find the .notEnabled accessibility trait. Instead, you can just configure a view as such with .disabled(true), and pass false to enable it. VoiceOver will announce it as "dimmed". https://developer.apple.com/documentation/swiftui/view/disabled(_:)

As with UIKit, in SwiftUI you can also add/remove a11y traits. But because of its declarative nature, you'll have to approach it in a slightly different way. A little nuance, but something that made me scratch my UIKit head when learning SwitUI.

The equivalent of using a .semanticGroup accessibilityContainerType in UIKit, would be to use the .accessibilityElement(children: ) modifier with the .contain option in SwiftUI. Here's a refresher with some use-cases: https://x.com/dadederk/status/1558790851496742914

In UIKit, to create an adjustable component we need to add the adjustable trait and override both accessibilityIncrement() and accessibilityDecrement(). In SwiftUI, everything you need is bundled in the accessibilityAdjustableAction(_:) modifier.

Grouping elements with .accessibility(children: .combine) doesn't always generate the best accessibility label. Comma-separating labels might sometimes not be ideal. But you can improve it by tweaking the labels/grouping of its children first.

Apple asks us to consider the combine behavior, before using ignore, for .accessibilityElement(children: ). And for good reason, if combine works, and later on you decide to change the UI, the accessibility attributes will be updated for you.

The .accessibilityElement(children: ) modifier with the .ignore argument does a similar thing to set the container view to be an accessibility element in UIKit. It is the default argument, so you can just say .accessibilityElement(). Because of this, you'll need to use other modifiers to make it accessible and manually configure an accessibility label and value, traits... when necessary. https://developer.apple.com/documentation/swiftui/view/accessibilityelement(children:) https://developer.apple.com/documentation/swiftui/accessibilitychildbehavior/ignore

Grouping elements in SwiftUI is extremely easy! You can use the .accessibility(children: .combine) modifier. And that's it! It merges properties. For example, generating an accessibility label by joining the children's ones, separated by commas.

If you want to know everything about how to "Tailor the VoiceOver experience in your data-rich apps" with the Accessibility Custom Content API, there is a WWDC21 session. https://developer.apple.com/videos/play/wwdc2021/10121/ When implementing accessibilityCustomContent, for any supplementary information, it returns an array that VoiceOver will announce in that given order. The value of the AXCustomContent first, then the label. Users can configure in VoiceOver's verbosity settings if it should say that there's more content available, or play a sound hinting that there is, or simply do nothing. So it should really be optional content as users might miss it.

When creating AXCustomContent objects for accessibilityCustomContent, you can specify the importance of the data. If it is high, it will always be presented by VoiceOver. You could potentially ask the user if that data is of importance to them.

Too much data can overwhelm users. Very little is an incomplete experience. It is hard to find a balance on verbosity and the users may have different preferences. To help with this issue, the AXCustomContent APIs let you mark data as optional.

We've spoken a lot about VoiceOver in the past 100 days. But who invented VoiceOver? The answer to this question and other fascinating stories from Mike Shebanek are in these amazing episodes of *13 Letters*: - Who invented VoiceOver? - Accessibility should be free > "Apple had been a worldwide leader in this. Late 70s, early 80s. The company was starting to fade, and so accessibility disappeared. Probably for about 10 years. 2004, and my manager says: hey, what are we doing? Nothing. We have nothing." > "Alan Brightman going to John Scully, the CEO, and Steve Jobs before Steve was ousted from the company, saying, 'If you're going to build a computer for the rest of us, then you should build a computer for all of us.'" > "Not just deliver a screen reader but change the whole idea. And that's when I thought, we need to build this in. We need to make this free. It needs to be everywhere. It needs to be there before you know you need it."

When making charts accessible, sometimes you may have just too many data points for the user to have to go one by one through all of them. In those cases, you can create accessibility elements that represent meaningful chunks of the graph.

Showing 121-135 of 234 posts

All Tags

Special thanks to

Quintin Balsdon

for helping extract the content from the original Twitter posts.