Accessibility & Localization
iOS Development — Production & Publishing
Chapter 2 · Accessibility & Localization
A real app ready to ship needs to genuinely work for users this course hasn't specifically written for yet — VoiceOver users, users who've increased their real system text size, and users in a real, different language. This chapter covers all three, at genuinely low real cost given how much SwiftUI already does by default.
VoiceOver: .accessibilityLabel() and .accessibilityHint()
A real Text view is already read aloud by VoiceOver automatically. An icon-only
Button, though, has nothing real for VoiceOver to announce on its own:
| Modifier | Real Role |
|---|---|
.accessibilityLabel() | What VoiceOver actually announces for this element — real, essential for anything with no visible real text of its own. |
.accessibilityHint() | An optional, real, brief description of what happens after activating it — genuinely supplementary, not a replacement for the label. |
A Real, Genuinely Free Default: Dynamic Type
.font(.body), .font(.headline),
.font(.largeTitle) — automatically scales with the user's own real Dynamic Type setting,
with genuinely zero extra code. Every Text view in TaskFlow since Fundamentals Chapter 5 has
already had this real, built-in support the whole time.
.font(.system(size: 17)) — a real, fixed point size — genuinely does not
scale with Dynamic Type. Reaching for a real, built-in text style instead of a hardcoded size is what
keeps this real accessibility support intact; it isn't automatic once a fixed size is used instead.
Grouping with .accessibilityElement(children:)
A TaskRow with several separate real subviews (title, priority badge) is, by real default,
announced by VoiceOver as several separate real elements — genuinely tedious to navigate one row at a
time. Combining them into one real, coherent announcement:
.combine merges every real child's own accessibility content into one real, single
announcement — "Buy milk, Medium," read once, rather than as two separate, disjointed real stops.
Localization: Xcode's Real String Catalog
Introduced with Xcode 15, 2023, the real String Catalog
(.xcstrings) is the current, recommended way to localize an app — replacing the real, older
.strings/.stringsdict file pair.
Xcode scans real, existing Text("...") and String(localized:) calls and populates the catalog automatically.
Every language's own real translation lives in one .xcstrings file, browsable in Xcode's own dedicated editor.
Genuine plural variations (0/1/few/many) are configured per string, no separate .stringsdict file needed.
Hands-On Exercises
Add a real .accessibilityLabel() and .accessibilityHint() to TaskFlow's own icon-only "Add" toolbar button, and explain, in your own words, why an icon-only button genuinely needs a label while a Text("Add") button would not.
Apply .accessibilityElement(children: .combine) to TaskFlow's own TaskRow, combining its title and priority badge into one real, single VoiceOver announcement.
Explain, in your own words, why using .font(.body) instead of .font(.system(size: 17)) throughout TaskFlow is what actually determines whether Dynamic Type genuinely works, even though both might display at a similar real size by default.
Chapter 2 Quick Reference
.accessibilityLabel()/.accessibilityHint()— real, essential for any element with no visible real text of its own, like an icon-only button- Dynamic Type works automatically with every real built-in text style — genuinely broken only by a hardcoded fixed point size
.accessibilityElement(children: .combine)— merges several real subviews into one coherent VoiceOver announcement- String Catalogs (
.xcstrings, Xcode 15/2023) — the real, current localization approach, with automatic string extraction and real, built-in pluralization - Product → Export/Import Localizations — the real, practical workflow for handing strings to a translator and bringing their work back in