Slide 1

Slide 1 text

Starting A11Y in iOS Nov 2019 CA11Y #2

Slide 2

Slide 2 text

Ryo Aoyama CyberAgent, Inc. CATS productivity team Twitter: @ra1028fe5 GitHub: @ra1028 OSS: DifferenceKit, Carbon, etc…

Slide 3

Slide 3 text

A11Y A C C E S S I B I L I T Y 11

Slide 4

Slide 4 text

Voice Over Voice Control Siri Shortcut Zoom Magnifier Larger Text Color Contrast etc…

Slide 5

Slide 5 text

Voice Over

Slide 6

Slide 6 text

Voice Over VoiceOver is a gesture-based screen reader that lets you enjoy using iPhone even if you don’t see the screen. “September event two thousand nineteen, Apple…”

Slide 7

Slide 7 text

The first step to get interested in Voice Over.

Slide 8

Slide 8 text

Enabling Voice Over in

Slide 9

Slide 9 text

https://support.apple.com/en-am/guide/iphone/iph3e2e2281/ios Learn VoiceOver gestures: Let's make sure that whether your app available for gestures and screen readers.

Slide 10

Slide 10 text

Enabling Voice Over with shortcut in

Slide 11

Slide 11 text

Youtube Airbnb Uber Eats Try to use the app with Voice Over habitually.

Slide 12

Slide 12 text

Voice Over in UIKit

Slide 13

Slide 13 text

The official programming guide says, “Standard UIKit controls and views are automatically accessible. When you use standard controls and views, much of the work of making your app accessible is done for you.”

Slide 14

Slide 14 text

Accessibility Attributes • Label • Traits • Hint • Frame • Value

Slide 15

Slide 15 text

Spoken by VoiceOver in order; “Value, Label, Traits, Hint” Traits are sometimes read before Label.

Slide 16

Slide 16 text

“બ୒தͷɺຊ೔։࠵ɺϘλϯ” “։࠵தͷϨʔε” When using standard UI such as UILabel or UIButton is read correctly by default. Label Label Trait Trait

Slide 17

Slide 17 text

A short word or phrase that succinctly describes the element, but doesn't identify the its type. Examples are "Add", not "Add button”. Some of elements such as UILabel or UIButton are having default label. Label var accessibilityLabel: String?

Slide 18

Slide 18 text

Label This isn't obvious the behavior of element and also disadvantageous for localization, so its better to set an accessibilityLabel. By default, if the button is set an icon only like below, the VoiceOver read an asset name.

Slide 19

Slide 19 text

Traits A combination of trait that single aspect of an element’s state, behavior, or usage. Static Text Image Button Link etc… Selected var accessibilityTraits: UIAccessibilityTraits

Slide 20

Slide 20 text

Hint A brief phrase that describes the results of an action. Examples are “Adds a title” or “Opens the shopping list.” Some controls have default value such as UIDatePicker. var accessibilityHint: String?

Slide 21

Slide 21 text

Hint The hint describes the element action itself or the results of performing it. If the role of the element is clarified by Label and Traits, there is no need to set Hint.

Slide 22

Slide 22 text

Hint This is not spoken by Voice Over if you set the switch off ’Speak Hints’ in setting app: Accessibility > VoiceOver > Verbosity

Slide 23

Slide 23 text

Frame The frame of the element in screen coordinates that specifies an element’s location and size. The UIView subclass defaults to the value same as `frame` property, otherwise zero. var accessibilityFrame: CGRect

Slide 24

Slide 24 text

Value The current value of an element. It's set by default such as UISlider or UITextField. var accessibilityValue: String?

Slide 25

Slide 25 text

Value print(slider.value) // 0.5 The `value` of UISlider is Float value, thus the result of following code is like `0.5`. But, the default accessibilityValue is the text `50%`. Like so, the accessibilityValue should be text that is more user-friendly.

Slide 26

Slide 26 text

There are many other APIs are provided, but as mentioned at the beginning, UIKit is accessible by default. Creating an app using standard UIKit elements whenever possible will help keep the app accessible.

Slide 27

Slide 27 text

A11Y Scanning Tools

Slide 28

Slide 28 text

Xcode Accessibility Inspector

Slide 29

Slide 29 text

Open inspector from the menu Xcode > Open Developer Tool > Accessibility Inspector

Slide 30

Slide 30 text

Automatically runs the VoiceOver in order of elements and revealing a11y setting of elements.

Slide 31

Slide 31 text

Expose the issues by audit and get a fix suggestion. Too many issues are lurk in our app

Slide 32

Slide 32 text

Overwrite the common a11y options to test.

Slide 33

Slide 33 text

Accessibility Inspector is just for Xcode GUI. Can’t used from Swift code or command line…

Slide 34

Slide 34 text

google/GSCXScanner iOS Accessibility scanner framework to catch a11y issues during development. Depending on google/GTXiLib.

Slide 35

Slide 35 text

target ‘App' do use_frameworks! pod 'GSCXScanner' end What to do to get started is only add following to Podfile:

Slide 36

Slide 36 text

We can always check the a11y on the app runtime from the ‘Perform Scan’ button.

Slide 37

Slide 37 text

Visualize the elements that has issues on the displaying screen.

Slide 38

Slide 38 text

And you can see issue details on the app.

Slide 39

Slide 39 text

In-app scanner allows members other than engineers to check a11y. It’s not available to be used for unit testing.

Slide 40

Slide 40 text

google/GTXiLib iOS Accessibility testing library that works with XCTest based frameworks.

Slide 41

Slide 41 text

Automatically runs all registered checks for a11y before tear-down on each tests. GTXiLib has XCTest integration and can be used with any XCTest-based frameworks such as google/EarlGrey. Can be introduced an arbitrary a11y checks.

Slide 42

Slide 42 text

final class MyTests: XCTestCase { override class func setUp() { super.setUp() GTXiLib.install( on: GTXTestSuite(allTestsIn: self), checks: GTXChecksCollection.allGTXChecks(), elementBlacklists: [] ) } func testXXX() { // Do any unit tests. } }

Slide 43

Slide 43 text

One or more elements FAILED the accessibility checks: > + Check "Element has Minimum Tappable Area" failed, Suggest increasing element's frame height to at least 44 for a suggested tappable area of at least 44X44

Slide 44

Slide 44 text

GTXiLib is extracts accessibility elements from the UI displayed on the screen on test environment. Can we control the app screen using XCUITest?

Slide 45

Slide 45 text

XCUITest is a black-box testing Control Installed ❌ Can’t access to process

Slide 46

Slide 46 text

GTXiLib is depends on UIApplication.shared, so it’s not allowed to runs on XCUITest-based testing process.

Slide 47

Slide 47 text

We can use google/EarlGrey v1 for UI automation in XCTest-based testing. final class MyTests: XCTestCase { override class func setUp() { super.setUp() GTXiLib.install( on: GTXTestSuite(allTestsIn: self), checks: GTXChecksCollection.allGTXChecks(), elementBlacklists: [] ) } func testXXX() { EarlGrey .selectElement(with: grey_text("Button")) .perform(grey_tap()) } }

Slide 48

Slide 48 text

Makes some pains, but “barely” possible to check a11y conformance with continuous integration.

Slide 49

Slide 49 text

Conclusion

Slide 50

Slide 50 text

Appropriate use of UIKit can adapt your app for minimal accessibility. Continuous testing for a11y having some pains likewise E2E testing, but it's possible. It’s important to include concerns about a11y in the UI/UX design and debugging process.

Slide 51

Slide 51 text

Thanks Twitter: @ra1028fe5 GitHub: @ra1028 Ryo Aoyama