# ๐จ๐ปโ๐ป 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}]"}