Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Accessibility on Apple Platforms: Beyond VoiceOver

Accessibility on Apple Platforms: Beyond VoiceOver

This hands-on workshop will get you started on making your app more accessible, by taking a look at VoiceOver, and a more in-depth look at dynamic type, Voice Control, and Full Keyboard Access — on any Apple platform your app supports.

It will also take a look at the tools that can help you verify the work you’ve done — including using the assistive technologies you’ll work on supporting.

## References

- https://www.basbroek.nl/getting-started-voiceover
- https://www.basbroek.nl/custom-tab-bar-accessibility
- https://developer.apple.com/videos/play/wwdc2021/10120/
- https://about.wetransfer.com/accessibility

79fe3c13c618a61329298bdd6a86ec42?s=128

Bas Broek

June 23, 2022
Tweet

More Decks by Bas Broek

Other Decks in Programming

Transcript

  1. Accessibility on Apple Platforms: Beyond VoiceOver Bas Broek @basthomas, June

    23, 2022 @ Appdevcon, Amsterdam, the Netherlands 1
  2. Bas Broek • iOS, Accessibility & more @ WeTransfer •

    Previously macOS Accessibility / VoiceOver @ Apple • Swift for Good co-author @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 2
  3. Introductions @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands

    3
  4. It's the right thing to do. @basthomas, June 23, 2022

    @ Appdevcon, Amsterdam, the Netherlands 4
  5. If only it were that easy. @basthomas, June 23, 2022

    @ Appdevcon, Amsterdam, the Netherlands 5
  6. ⚠ Hands-on @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the

    Netherlands 6
  7. My goal: Leave with improved accessibility in your app that

    you can demo @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 7
  8. Please interrupt me if you have any questions @basthomas, June

    23, 2022 @ Appdevcon, Amsterdam, the Netherlands 8
  9. ... and/or if you want to demo something! @basthomas, June

    23, 2022 @ Appdevcon, Amsterdam, the Netherlands 9
  10. A note on "ticket- creating" mode @basthomas, June 23, 2022

    @ Appdevcon, Amsterdam, the Netherlands 10
  11. "Evolution" of Accessibility on Apple platforms • VoiceOver, Switch Control

    • Voice Control • Full Keyboard Access • ... and more; think zoom, Dynamic Type, Reduce Motion etc. • ... as well as Dark Mode, Back Tap, Siri, haptics @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 11
  12. Two layers of accessibility @basthomas, June 23, 2022 @ Appdevcon,

    Amsterdam, the Netherlands 12
  13. VoiceOver @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands

    13
  14. UIKit accessibilityLabel accessibilityTraits accessibilityValue accessibilityHint @basthomas, June 23, 2022 @

    Appdevcon, Amsterdam, the Netherlands 14
  15. UIKit accessibilityLabel - "Volume" accessibilityTraits - .adjustable accessibilityValue - "56%"

    accessibilityHint - "Swipe up or down to adjust." @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 15
  16. SwiftUI .accessibilityLabel("Volume") .accessibilityAdjustableAction { direction in } .accessibilityValue("50%") .accessibilityHint("Swipe up

    or down to adjust.") @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 16
  17. Let's verify @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the

    Netherlands 17
  18. Custom Content @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the

    Netherlands 18
  19. import Accessibility class MyObjectContainingTweetCell: AXCustomContentProvider { var _accessibilityCustomContent: [AXCustomContent] =

    [] var accessibilityCustomContent: [AXCustomContent]! { get { _accessibilityCustomContent } set { _accessibilityCustomContent = newValue } } func setupTweetCell(with tweet: Tweet) { accessibilityCustomContent = [ .init( label: NSLocalizedString("Replies", comment: ""), value: String(describing: tweet.replies.count) ) ] } } @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 19
  20. .accessibilityCustomContent( "Replies", String(describing: tweet.replies.count) ) @basthomas, June 23, 2022 @

    Appdevcon, Amsterdam, the Netherlands 20
  21. Demo @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands

    21
  22. Performing Escapes @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the

    Netherlands 22
  23. override func accessibilityPerformEscape() { dismiss() return true } .accessibilityAction(.escape) {}

    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 23
  24. Demo @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands

    24
  25. Magic tap @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the

    Netherlands 25
  26. /// Performs a salient action. @basthomas, June 23, 2022 @

    Appdevcon, Amsterdam, the Netherlands 26
  27. override func accessibilityPerformMagicTap() { transferFile() return true } .accessibilityAction(.magicTap) {}

    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 27
  28. Demo @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands

    28
  29. Image exploration @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the

    Netherlands 29
  30. .accessibilityTraits.insert(.image) .accessibilityAddTraits(.isImage) @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the

    Netherlands 30
  31. Demo @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands

    31
  32. Voice Control @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the

    Netherlands 32
  33. accessibilityUserInputLabels @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands

    33
  34. ! @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands

    34
  35. /// The default value for this property is an empty

    array /// unless the element is a UIKit control. /// In that case, the value is an array with /// an appropriate label, if different from `accessibilityLabel`. /// /// Use this property when the `accessibilityLabel` isn't appropriate for /// dictated or typed input. /// For example, an element that contains additional descriptive /// information in its `accessibilityLabel` can return a more concise label. /// /// The primary label is first in the array, optionally followed /// by alternative labels in descending order of importance. /// /// If this property returns an empty array or an invalid value, /// the system uses `accessibilityLabel` instead. @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 35
  36. /// The default value for this property is an empty

    array /// unless the element is a UIKit control. /// In that case, the value is an array with /// an appropriate label, if different from `accessibilityLabel`. /// /// Use this property when the `accessibilityLabel` isn't appropriate for /// dictated or typed input. /// For example, an element that contains additional descriptive /// information in its `accessibilityLabel` can return a more concise label. /// /// The primary label is first in the array, optionally followed /// by alternative labels in descending order of importance. /// /// If this property returns an empty array or an invalid value, /// the system uses `accessibilityLabel` instead. @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 36
  37. "TAP TO COPY LINK" "Tap 'tap to copy link'" @basthomas,

    June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 37
  38. "TAP TO COPY LINK" "Tap 'tap to copy link'" "Tap

    'copy link'" @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 38
  39. "It's Complicated: Inside an A. Lange & Söhne Split-Seconds Chronograph"

    "Tap 'It's Complicated: Inside an A. Lange & Söhne Split-Seconds Chronograph'" @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 39
  40. "It's Complicated: Inside an A. Lange & Söhne Split-Seconds Chronograph"

    "Tap 'It's Complicated: Inside an A. Lange & Söhne Split-Seconds Chronograph'" "Tap 'article, 1'" @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 40
  41. UIKit copyLinkButton.accessibilityLabel = "Tap to copy link" copyLinkButton.accessibilityUserInputLabels = [

    "Copy link", "Copy" ] article.accessibilityLabel = "It's Complicated: Inside an A. Lange & Söhne Split-Seconds Chronograph" article.accessibilityUserInputLabels = [ "Article", "News", article.accessibilityLabel ] @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 41
  42. SwiftUI .accessibilityLabel( "Tap to copy link" ) .accessibilityInputLabels([ "Copy link",

    "Copy" ]) .accessibilityLabel( "It's Complicated: Inside an A. Lange & Söhne Split-Seconds Chronograph" ) .accessibilityInputLabels([ "Article", "News", "It's Complicated: Inside an A. Lange & Söhne Split-Seconds Chronograph" ]) @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 42
  43. Demo @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands

    43
  44. Full Keyboard Access @basthomas, June 23, 2022 @ Appdevcon, Amsterdam,

    the Netherlands 44
  45. /// The default value for this property is an empty

    array /// unless the element is a UIKit control. /// In that case, the value is an array with /// an appropriate label, if different from `accessibilityLabel`. /// /// Use this property when the `accessibilityLabel` isn't appropriate for /// dictated or typed input. /// For example, an element that contains additional descriptive /// information in its `accessibilityLabel` can return a more concise label. /// /// The primary label is first in the array, optionally followed /// by alternative labels in descending order of importance. /// /// If this property returns an empty array or an invalid value, /// the system uses `accessibilityLabel` instead. @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 45
  46. ! @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands

    46
  47. Demo @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands

    47
  48. A lot of demos Consider using assistive technologies for your

    product demos! @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 48
  49. Championing accessibility 1-1 sessions (may) help @basthomas, June 23, 2022

    @ Appdevcon, Amsterdam, the Netherlands 49
  50. Loopin' back • VoiceOver support gets you most of the

    way there • Adding Voice Control support will get you ±all the way • ... to also support Full Keyboard Access on iOS! @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 50
  51. One last thing... @basthomas, June 23, 2022 @ Appdevcon, Amsterdam,

    the Netherlands 51
  52. WeTransfer: Mission Accessible @basthomas, June 23, 2022 @ Appdevcon, Amsterdam,

    the Netherlands 52
  53. Thank you! @basthomas @basthomas, June 23, 2022 @ Appdevcon, Amsterdam,

    the Netherlands 53
  54. References • https://www.basbroek.nl/getting-started-voiceover • https://www.basbroek.nl/custom-tab-bar-accessibility • https://developer.apple.com/videos/play/ wwdc2021/10120/ • https://about.wetransfer.com/accessibility

    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 54