Highlight
Apple illustrates through real-life examples from visually and hearing-impaired developers that accessibility improvements can start with button labels, VoiceOver testing, and multi-sensory feedback, allowing the same app to be used by more users and developers.
Core Content
Many teams put accessibility as a pre-launch check. After finishing the interface, open VoiceOver and try it again. If you find that buttons are unreadable, pictures have no explanations, and interactions rely on sound, list them as tasks to fix later.
The pain points given in this speech are more specific. One developer mentioned that there was an app where the graphical buttons had no labels, making it impossible for VoiceOver users to know what the buttons meant. After the developer added the tags, it only took a day for the app to become basically accessible.
Apple did not turn this talk into an API release. It lets visually and hearing-impaired developers talk about how they work. Hearing-impaired developers will naturally check whether the app can run without sound. Visually impaired developers use screen readers every day to write code, test apps, and submit bugs.
This changes the starting point for accessibility. Developers don’t need to design a separate version first. Start by doing a version of the same thing so that buttons have names, VoiceOver can read states, sound prompts have visual alternatives, and visual tasks have audio guidance.
Start with a button label
With a completely inaccessible app, the problem may be minor: graphical buttons have no labels. Screen readers can only pronounce “button” and the user has no idea what will happen next.
After adding labels, users can understand the interface. This change does not require a schema rewrite. It requires developers to hand over the semantics of the control to the system.
The tool itself must also be accessible
When hearing-impaired developers receive a VoiceOver bug, the question becomes: How can I test if I can’t hear VoiceOver read aloud?
The answer is VoiceOver’s caption bar. It displays what VoiceOver speaks as text, such as “Tweets and replies, Button.” This small feature allows hearing-impaired developers to debug VoiceOver issues.
Make products based on personal pain points
Seeing AI comes from the personal needs of visually impaired developers. It describes the world around it, reads text, and recognizes people and objects. When a barcode is scanned, the team provides audio guidance in a “hot or cold” manner: the closer to the target, the faster the beep.
Cardzilla comes from a hearing-impaired developer’s ride-hailing experience. He originally used Notes App to communicate with the driver, but the text was too small. So I made an app that enlarges text, making it easier for the other party to read and making communication faster.
Detailed Content
1. Provide readable labels for graphic buttons
(02:05) The first concrete example in the talk is button labels. An app cannot be used by VoiceOver users because the graphical buttons do not have labels. After the developer adds the tags, the app becomes basically accessible.
In SwiftUI, graphic buttons can be usedaccessibilityLabelProvide semantic names. Below is a complete minimal example.
import SwiftUI
struct PlaybackControls: View {
@State private var isPlaying = false
var body: some View {
Button {
isPlaying.toggle()
} label: {
Image(systemName: isPlaying ? "pause.fill" : "play.fill")
}
.accessibilityLabel(isPlaying ? "Pause" : "Play")
}
}
struct PlaybackControls_Previews: PreviewProvider {
static var previews: some View {
PlaybackControls()
}
}
Key Points:
import SwiftUIIntroducing SwiftUI, examples can be directly put into SwiftUI App or run in preview. -@State private var isPlaying = falseSave the playback status and the interface will be updated after clicking the button. -Button { ... } label: { ... }Create a button with only an icon. -Image(systemName:)Show play or pause icon depending on status. -.accessibilityLabel(isPlaying ? "Pause" : "Play")Give the graphic button a name that VoiceOver can read. -PlaybackControls_PreviewsProvides Xcode preview entrance to facilitate Accessibility Preview inspection.
2. Use the same version to serve all users
(01:43) Avid developers say the goal is not to make a “blind version of Pro Tools.” The goal is a version that everyone can step up and use.
This principle is implemented in the code, usually by placing the status, action and label on the original control, so that the system auxiliary functions can read the same set of interfaces. The following example makes a mute button into the same control without duplicating an additional accessibility interface.
import SwiftUI
struct MuteButton: View {
@State private var isMuted = false
var body: some View {
Button {
isMuted.toggle()
} label: {
Label(isMuted ? "Unmute" : "Mute",
systemImage: isMuted ? "speaker.slash.fill" : "speaker.wave.2.fill")
}
.accessibilityValue(isMuted ? "Muted" : "Sound on")
}
}
struct MuteButton_Previews: PreviewProvider {
static var previews: some View {
MuteButton()
}
}
Key Points:
@State private var isMuted = falseSave the current sound state. -ButtonIt is an interactive portal shared by all users. -LabelContains both text and system icons, and names are available to both visual and VoiceOver users. -systemImageAs the status changes, the visual interface can express the mute status. -.accessibilityValueSpeaks the current value to let the user know whether the button now corresponds to “Muted” or “Sound on”.
3. Allow users without voice to check VoiceOver
(03:03) A hearing-impaired developer receives a VoiceOver bug. He discovered that VoiceOver has a subtitle bar that can display spoken content as text. The subtitles in the speech read “Tweets and replies, Button”, “Media, Button” and “Likes, Button”.
When developing an application, you can prepare readable labels and visible text at the same time. In this way, hearing-impaired testers can check the VoiceOver output through the subtitle bar, and visually impaired users can hear the same semantics through a screen reader.
import SwiftUI
struct ProfileTabs: View {
var body: some View {
HStack {
Button("Tweets and replies") {}
Button("Media") {}
Button("Likes") {}
}
.padding()
}
}
struct ProfileTabs_Previews: PreviewProvider {
static var previews: some View {
ProfileTabs()
}
}
Key Points:
HStackThree buttons are arranged horizontally, corresponding to the three focusable elements in the speech subtitle bar. -Button("Tweets and replies") {}With text titles, VoiceOver can read them directly. -Button("Media") {}andButton("Likes") {}Keep the same pattern to reduce the chance of missing tags. -.padding()Only affects the visual layout and does not change the accessibility semantics.- Open the VoiceOver subtitle bar when running, so testers can check the reading results with text.
4. Provide audio guidance for camera tasks
(03:59) The Seeing AI team discovered that users need to know whether the camera is pointed at the target when scanning a barcode. The team uses a “hot or cold” game rule: the closer to the barcode, the faster the beep will be.
This idea is suitable for all tasks that require the user to aim at the target. The code can first abstract “proximity” into a value from 0 to 1, and then convert it into a beep interval.
import Foundation
struct BarcodeAudioGuide {
func beepInterval(for proximity: Double) -> TimeInterval {
let clampedProximity = min(max(proximity, 0), 1)
let slowestInterval = 1.0
let fastestInterval = 0.15
return slowestInterval - (slowestInterval - fastestInterval) * clampedProximity
}
}
let guide = BarcodeAudioGuide()
let interval = guide.beepInterval(for: 0.75)
print(interval)
Key Points:
import FoundationintroduceTimeInterval。BarcodeAudioGuideSave calculation logic for barcode audio guidance. -beepInterval(for:)receiving proximity,0means far,1means near. -min(max(proximity, 0), 1)Limit inputs to 0 to 1 to avoid outliers affecting calculations. -slowestIntervalis the slowest beep interval. -fastestIntervalis the fastest beep interval. -returnThe interval is shortened according to the proximity. The closer to the target, the smaller the return value. -print(interval)Let the example run directly and observe the results.
5. Enlarge text to solve face-to-face communication
(04:27) Cardzilla’s starting point is very everyday: when a hearing-impaired developer takes a taxi, he uses Notes App to read text to the driver, but the text is too small. So he made an app that amplifies text and improves communication efficiency.
This function is not complicated. The key is to make the input content immediately large and centered, making it easier for the other party to read.
import SwiftUI
struct LargeMessageCard: View {
@State private var message = "Please take me home."
var body: some View {
VStack(spacing: 24) {
TextEditor(text: $message)
.frame(height: 120)
.border(Color.secondary)
Text(message)
.font(.system(size: 56, weight: .bold))
.multilineTextAlignment(.center)
.minimumScaleFactor(0.4)
.padding()
}
.padding()
}
}
struct LargeMessageCard_Previews: PreviewProvider {
static var previews: some View {
LargeMessageCard()
}
}
Key Points:
@State private var messageSave the text you want to show the other person. -TextEditor(text: $message)Allow users to edit content. -.frame(height: 120)Limit the height of the input area to allow space for the display area. -Text(message)Display the enlarged content. -.font(.system(size: 56, weight: .bold))Use large font sizes and bold fonts to improve readability at a distance. -.multilineTextAlignment(.center)Center multiline text. -.minimumScaleFactor(0.4)Automatically shrink text when it is too long to reduce truncation.
Core Takeaways
-
What to do: Add readable names to all icon buttons. Why it’s worth doing: The cases in the speech showed that the lack of button labels will make the app completely inaccessible; after adding the labels, the app can be basically usable within a day. How to start: Open the frequently used page and check the icons one by one
Button, add in SwiftUI.accessibilityLabel, set in UIKitaccessibilityLabel。 -
What to do: Add visual inspection paths for voice and sound prompts. Why it’s worth doing: Hearing-impaired developers rely on the VoiceOver subtitle bar to debug VoiceOver bugs, indicating that testing tools and debugging information need to be presented across the senses. How to get started: Open the VoiceOver subtitle bar and check the text read by each focusable element; add text, icons or vibration feedback to audio-dependent status prompts.
-
What to do: Add “closer and denser” feedback to camera scans. Why it’s worth doing: Seeing AI’s barcode scanning uses a beep frequency to help users aim at the target, solving the operational problem when the viewfinder screen cannot be seen. How to start: First calculate the confidence or distance of the target in the screen, and map it into beep intervals, vibration rhythm or screen prompts.
-
What to do: Create a face-to-face communication model with large characters. Why it’s worth doing: Cardzilla’s scenario comes from taxi communication, and the core requirement is to let the other party understand the text quickly. How to start: Use
TextEditorEnter content in large font sizeTextDisplay in full screen and add voice input entrance. -
What to do: Incorporate users with disabilities into the beta testing process. Why it’s worth doing: The talk mentioned that accessibility requires input from beta testers within the company and outside the company; team diversity will lead to more direct problem discovery. How to get started: Explicitly welcome VoiceOver, subtitles, keyboard access, Switch Control user feedback in the TestFlight recruiting instructions, and categorize feedback into specific pages and controls.
Related Sessions
- SwiftUI Accessibility: Beyond the basics — Learn the specific implementation of SwiftUI accessibility modifiers, grouping, focus, and rotor.
- Support Full Keyboard Access in your iOS app — Allows iOS apps to navigate and operate using only the keyboard.
- Tailor the VoiceOver experience in your data-rich apps — Provides leaner, more expandable VoiceOver information for data-intensive interfaces.
- Bring accessibility to charts in your app — Convert charts into data structures that are navigable by VoiceOver and playable by Audio Graph.
- The process of inclusive design — Incorporate inclusive design into team building, ideation, development, and testing processes.
Comments
GitHub Issues · utterances