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

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

    View Slide

  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

    View Slide

  3. Introductions
    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 3

    View Slide

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

    View Slide

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

    View Slide


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

    View Slide

  7. My goal:
    Leave with improved accessibility
    in your app that you can demo
    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 7

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  12. Two layers of
    accessibility
    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 12

    View Slide

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

    View Slide

  14. UIKit
    accessibilityLabel
    accessibilityTraits
    accessibilityValue
    accessibilityHint
    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 14

    View Slide

  15. UIKit
    accessibilityLabel - "Volume"
    accessibilityTraits - .adjustable
    accessibilityValue - "56%"
    accessibilityHint - "Swipe up or down to adjust."
    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 15

    View Slide

  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

    View Slide

  17. Let's verify
    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 17

    View Slide

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

    View Slide

  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

    View Slide

  20. .accessibilityCustomContent(
    "Replies",
    String(describing: tweet.replies.count)
    )
    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 20

    View Slide

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

    View Slide

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

    View Slide

  23. override func accessibilityPerformEscape() {
    dismiss()
    return true
    }
    .accessibilityAction(.escape) {}
    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 23

    View Slide

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

    View Slide

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

    View Slide

  26. /// Performs a salient action.
    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 26

    View Slide

  27. override func accessibilityPerformMagicTap() {
    transferFile()
    return true
    }
    .accessibilityAction(.magicTap) {}
    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 27

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

  48. A lot of demos
    Consider using assistive
    technologies for your product
    demos!
    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 48

    View Slide

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

    View Slide

  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

    View Slide

  51. One last thing...
    @basthomas, June 23, 2022 @ Appdevcon, Amsterdam, the Netherlands 51

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide