# ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป Basic VoiceOver in UIKit William Kuo @iOSTaipei --- # Overview - Introduce VoiceOver - Debug / Test VoiceOver - VoiceOver basic APIs - VoiceOver post changes and status - VoiceOver Numbers --- # VoiceOver - Screen Reader - [WWDC17: What's New in Accessibility](https://developer.apple.com/videos/play/wwdc2017/215/) - Over 1 billion - 1 in 7 - Check it! --- # Debug / Test VoiceOver - Active VoiceOver - VoiceOver Common gesture ---- # Active VoiceOver - ๐Ÿ“ฑ Device: By Siri ใ€Œ้–‹ๅ•Ÿ / ้—œ้–‰ๆ—็™ฝใ€ - ๐Ÿ“ฑ Device: By triple tap shortcut (่จญๅฎš > ่ƒŒ้ข่ผ•้ปž > ้ปžไธ‰ไธ‹้–‹ๅ•Ÿๆ—็™ฝ) - ๐Ÿ“ฑ Device: [Apple: ๅœจ iPhone ไธŠ้–‹ๅ•Ÿๅ’Œ็ทด็ฟ’ใ€Œๆ—็™ฝใ€](https://support.apple.com/zh-tw/guide/iphone/iph3e2e415f/ios) - ๐Ÿ’ป๏ธ Mac: Accessibility Inspector ---- # VoiceOver Common Gestures - Scroll: three finger scroll - Read element: one finger tap - Enter element: one finger double-tap - Scroll to read: one finger scroll - Swipe left / right: read previous / next element - Back to home: one finger bottom edge to top, release finger while first phone vibration - ใ€ŒDark modeใ€: three finger triple-tap --- # VoiceOver Basic APIs ---- # accessibilityLabel Make sure every element has `label` to read. ---- # accessibilityLabel - A localized string that identifies the accessibility element. - All about `context`: "Add" โ†’ "Add note", "Add to favorite" - Leave traits in traits: - โ›”๏ธ "Add button" โ†’ "Add button button" - โœ… "Add" โ†’ "Add button" > [WWDC19 Writing Great Accessibility Labels](https://developer.apple.com/videos/play/wwdc2019/254/) ---- # VoiceOver vars ```swift= extension NSObject { open var isAccessibilityElement: Bool open var accessibilityLabel: NSString? open var accessibilityTraits: UIAccessibilityTraits open var accessibilityValue: NSString? open var accessibilityHint: NSString? } ``` ---- # VoiceOver vars read order - accessibilityLabel: ๅ…ƒไปถ็”จ้€”ๆ่ฟฐ โ†’ "้ฃ›่ˆชๆจกๅผ" - accessibilityValue: ๅ…ƒไปถๆ•ธๅ€ผ โ†’ "้—œ้–‰" - accessibilityTraits: ๅ…ƒไปถ็จฎ้กž โ†’ .button - accessibilityHint: ๅ…ƒไปถ่ฃœๅ……่ชชๆ˜Ž โ†’ "้ปžๅ…ฉไธ‹ไพ†ๅˆ‡ๆ›่จญๅฎš" ---- # System Default In UIKit, views like `UILabel`, `UITextField`, `UIProgressView`, and all views that extend `UIControl` **are accessible by default**. `UIImageView`, `UIView` itself, custom views that inherit from `UIView`, and container views like UIStackView are **not accessible by default**. > [Medium: How to develop accessible iOS apps - Jeroen de Vrind](https://medium.com/short-swift-stories/accessibility-element-2d55cefdf9d7) ---- # accessibilityTraits Categories - link - button - image - header - **updatesFrequently** - ... ```swift= .accessibilityTraits |= UIAccessibilityTraitButton // Apple .accessibilityTraits = [.button, .selected] ``` ---- # accessibilityElements - Change read order (swipe-left/right read) - Prevent whole cell focus --- # VoiceOver post changes and status ---- # Push `changes` notification to User ```swift= // Notify user sectionHeader's label / value changed with element-focus. UIAccessibility.post(notification: .layoutChanged, argument: self.sectionHeader) // Notify user something changed and nothing-focus. UIAccessibility.post(notification: .screenChanged, argument: "ๅทฒๆป‘ๅ‹•ๅˆฐๆœ€ๅบ•้ƒจ") ``` ---- # Check VoiceOver status ```swift= // Hide un-need things when voiceOver is running. UIAccessibility.isVoiceOverRunning // Listen to voiceOver status NotificationCenter.default.addObserver(self, selector: #selector(voiceOverStatusDidChanged), name: UIAccessibility.voiceOverStatusDidChangeNotification, object: nil) ``` --- # VoiceOver Numbers - "2200" โ†’ "ๅ…ฉๅƒๅ…ฉ็™พ" - "2 2 0 0" โ†’ ๅœไฟƒๆ™‚้–“็Ÿญ็š„ "2" "2" "0" "0" - "2,2,0,0" โ†’ ๅœไฟƒๆ™‚้–“้•ท็š„ "2" "2" "0" "0" - "2021/09/14" โ†’ Use Dateformatter --- # Things I don't know or not good at - Accessibility tree - Difference between isAccessibilityElement / accessibilityElementsHidden - Group elements --- Thank you ---
{"metaMigratedAt":"2023-06-16T10:18:10.707Z","metaMigratedFrom":"Content","title":"๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป Basic VoiceOver in UIKit","breaks":true,"contributors":"[{\"id\":\"a56a0e18-8c9e-48b1-86be-105d679a9b4b\",\"add\":4324,\"del\":395}]"}
    768 views