swift-accessibility-skill

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Platform Accessibility

平台无障碍设计

Overview

概述

Apply accessibility for SwiftUI, UIKit, and AppKit across all supported platforms. Covers all 9 App Store Accessibility Nutrition Label categories — VoiceOver, Voice Control, Larger Text, Dark Interface, Differentiate Without Color, Sufficient Contrast, Reduced Motion, Captions, and Audio Descriptions.
This skill prioritizes native platform APIs (which provide free automatic support) and fact-based guidance without architecture opinions.
为所有支持平台的SwiftUI、UIKit和AppKit应用无障碍设计。涵盖App Store无障碍营养标签的全部9个类别——VoiceOver、Voice Control、大字体、深色界面、无颜色区分、足够对比度、减少动态效果、字幕和音频描述。
本技能优先使用原生平台API(可免费提供自动支持),并提供基于事实的指导,不涉及架构层面的观点。

First-Draft Rules

初稿规则

Include accessibility in the first draft — never write a bare element and patch it later. Retrofitting accessibility is harder, gets skipped, and produces worse results than building it in from the start.
No inline commentary unless a pattern is non-obvious. Mark inferred labels with
// [VERIFY]
because SF Symbol names don't always match the intended user-facing meaning.
SituationRequired on first write
Button
/
NavigationLink
— icon-only
.accessibilityLabel("…")
with
// [VERIFY]
Button
/
NavigationLink
— visible text
Nothing extra — text is the label automatically
Image
— meaningful
.accessibilityLabel("…")
Image
— decorative
.accessibilityHidden(true)
withAnimation
/
.transition
/
.animation
@Environment(\.accessibilityReduceMotion)
+ gate animation
.font(.system(size:))
Replace with
.font(.body)
or
@ScaledMetric
Color conveys state/statusAdd shape, icon, or text alongside color
onTapGesture
on non-
Button
.accessibilityElement(children: .ignore)
+
.accessibilityAddTraits(.isButton)
+
.accessibilityLabel
Custom slider / toggle / stepper
.accessibilityRepresentation { … }
or
.accessibilityValue
+
.accessibilityAdjustableAction
Async content changePost announcement with availability guards (
AccessibilityNotification.Announcement
on iOS 17+, fallback to
UIAccessibility.post
)
System
.sheet
/
.fullScreenCover
Nothing extra — SwiftUI traps focus automatically (custom overlays still need focus management)
AVPlayer
/ video
Use
AVPlayerViewController
— captions and Audio Descriptions for free
Custom tappable view
.frame(minWidth: 44, minHeight: 44)
Any new SwiftUI viewVerify with Xcode Canvas Variants (see Accessibility Summary)
NSButton
— icon-only (AppKit)
setAccessibilityLabel("…")
with
// [VERIFY]
Custom
NSView
interactive element (AppKit)
setAccessibilityElement(true)
+ role (
setAccessibilityRole(.button)
) + label
AppKit modal/popup UITrap focus and ensure dismiss action is keyboard + VoiceOver reachable
Any new AppKit view/controllerVerify with Accessibility Inspector and full keyboard navigation
Prefer native controls (
Button
,
Toggle
,
Stepper
,
Slider
,
Picker
,
TextField
) — they get full accessibility automatically. Custom interactive views require explicit work. For AppKit, prefer native controls (
NSButton
,
NSPopUpButton
,
NSSlider
,
NSSegmentedControl
,
NSTextField
) before custom
NSView
interaction.
Example — icon-only button:
swift
Button {
    shareAction()
} label: {
    Image(systemName: "square.and.arrow.up")
}
.accessibilityLabel("Share") // [VERIFY] confirm label matches intent
Example — gating animation on Reduce Motion:
swift
@Environment(\.accessibilityReduceMotion) private var reduceMotion

withAnimation(reduceMotion ? nil : .spring()) {
    isExpanded.toggle()
}
Full testing and verification procedures →
references/testing-auditing.md
初稿阶段就融入无障碍设计——切勿先编写基础元素再后期修补。后期补充无障碍设计难度更大,容易被遗漏,且效果远不如从一开始就构建到位。
除非模式非显而易见,否则不要添加内联注释。对推断出的标签标记
// [VERIFY]
,因为SF Symbol名称并不总是与用户预期的字面含义匹配。
场景首次编写时必须添加
Button
/
NavigationLink
— 仅图标
// [VERIFY]
.accessibilityLabel("…")
Button
/
NavigationLink
— 带可见文本
无需额外操作——文本会自动作为标签
Image
— 有实际意义
.accessibilityLabel("…")
Image
— 装饰性
.accessibilityHidden(true)
withAnimation
/
.transition
/
.animation
@Environment(\\.accessibilityReduceMotion)
+ 动态效果开关
.font(.system(size:))
替换为
.font(.body)
@ScaledMetric
颜色用于传达状态/状态信息在颜色之外添加形状、图标或文本
Button
元素使用
onTapGesture
.accessibilityElement(children: .ignore)
+
.accessibilityAddTraits(.isButton)
+
.accessibilityLabel
自定义滑块/开关/步进器
.accessibilityRepresentation { … }
.accessibilityValue
+
.accessibilityAdjustableAction
异步内容变更带版本兼容判断的公告推送(iOS 17+使用
AccessibilityNotification.Announcement
,旧版本回退到
UIAccessibility.post
系统
.sheet
/
.fullScreenCover
无需额外操作——SwiftUI会自动捕获焦点(自定义浮层仍需焦点管理)
AVPlayer
/ 视频
使用
AVPlayerViewController
——可免费获得字幕和音频描述支持
自定义可点击视图
.frame(minWidth: 44, minHeight: 44)
任何新的SwiftUI视图使用Xcode Canvas变体(查看无障碍摘要)进行验证
NSButton
— 仅图标(AppKit)
// [VERIFY]
setAccessibilityLabel("…")
自定义
NSView
交互元素(AppKit)
setAccessibilityElement(true)
+ 角色(
setAccessibilityRole(.button)
) + 标签
AppKit模态/弹窗UI捕获焦点并确保关闭操作可通过键盘和VoiceOver访问
任何新的AppKit视图/控制器使用无障碍检查器和全键盘导航进行验证
优先使用原生控件(
Button
Toggle
Stepper
Slider
Picker
TextField
)——它们会自动获得完整的无障碍支持。自定义交互视图需要显式配置。 对于AppKit,在自定义
NSView
交互之前,优先使用原生控件(
NSButton
NSPopUpButton
NSSlider
NSSegmentedControl
NSTextField
)。
示例 — 仅图标按钮:
swift
Button {
    shareAction()
} label: {
    Image(systemName: "square.and.arrow.up")
}
.accessibilityLabel("Share") // [VERIFY] confirm label matches intent
示例 — 根据减少动态效果设置开关动画:
swift
@Environment(\\.accessibilityReduceMotion) private var reduceMotion

withAnimation(reduceMotion ? nil : .spring()) {
    isExpanded.toggle()
}
完整的测试和验证流程 →
references/testing-auditing.md

Workflow

工作流程

Reference Routing Rule

参考路由规则

Before answering, select one primary reference file that best matches the user's intent and load it first. Load additional reference files only when the request explicitly spans multiple domains (for example, VoiceOver + Dynamic Type + WCAG mapping) or when the primary file does not cover a required criterion.
在回答之前,选择一个主要参考文件,使其最匹配用户意图并优先加载。 只有当请求明确涉及多个领域(例如VoiceOver + Dynamic Type + WCAG映射)或主要文件未覆盖必要标准时,才加载额外的参考文件。

1) Implement new code

1) 实现新代码

Apply First-Draft Rules — accessibility in the first draft, no commentary. For APIs introduced after iOS 15, always add
#available
guards and provide older-OS fallback behavior. After writing, verify against the First-Draft Rules table — fix any gaps before outputting. After the code, append an Accessibility Summary (see below).
应用初稿规则——在初稿阶段融入无障碍设计,无需注释。 对于iOS 15之后引入的API,始终添加
#available
版本兼容判断并提供旧系统的回退行为。 编写完成后,对照初稿规则表进行验证——输出前修复所有遗漏。 代码之后,附加无障碍摘要(见下文)。

2) Improve or fix existing code

2) 改进或修复现有代码

Apply fixes silently, no commentary. For APIs introduced after iOS 15, always add
#available
guards and provide older-OS fallback behavior. After fixing, verify against the First-Draft Rules table — fix any gaps before outputting. After the code, append an Accessibility Summary.
  • For transformation patterns →
    examples/before-after-swiftui.md
    ,
    examples/before-after-uikit.md
    , or
    examples/before-after-appkit.md
  • For platform issues →
    references/platform-specifics.md
静默应用修复,无需注释。 对于iOS 15之后引入的API,始终添加
#available
版本兼容判断并提供旧系统的回退行为。 修复完成后,对照初稿规则表进行验证——输出前修复所有遗漏。 代码之后,附加无障碍摘要
  • 转换模式参考 →
    examples/before-after-swiftui.md
    examples/before-after-uikit.md
    examples/before-after-appkit.md
  • 平台特定问题参考 →
    references/platform-specifics.md

3) Audit existing code

3) 审核现有代码

Only when user explicitly asks ("audit", "how accessible is this?", "review accessibility").
Quick fix mode — when the user asks for blocker-only/critical-only scope (for example: "just fix the blockers", "quick fix", "critical only"): address only Blocks Assistive Tech and Degrades Experience issues. Skip Incomplete Support.
Comprehensive mode (default) — address all severity levels including Incomplete Support and Nutrition Label gaps.
  • Identify issues by category → Triage Playbook below
  • Format with Audit Output Format below
  • For WCAG compliance mapping →
    references/wcag-mapping.md
  • Hand off to QA →
    resources/qa-checklist.md
仅当用户明确要求时(如"audit"、"这个的无障碍性如何?"、"审核无障碍设计")执行此操作。
快速修复模式——当用户要求仅处理阻塞性/关键性问题时(例如:"只修复阻塞问题"、"快速修复"、"仅处理关键问题"):仅解决阻塞辅助技术和降低体验的问题,跳过不完整支持的问题。
全面模式(默认)——处理所有严重程度的问题,包括不完整支持和营养标签缺失。
  • 按类别识别问题 → 下文的分类处理手册
  • 按照审核输出格式排版
  • WCAG合规映射参考 →
    references/wcag-mapping.md
  • 移交QA参考 →
    resources/qa-checklist.md

4) Prepare Nutrition Label recommendation

4) 准备营养标签建议

references/nutrition-labels.md
— all 9 categories with official pass/fail criteria
When the user asks to prepare or draft an App Store Accessibility Nutrition Label recommendation, output this format:
**Accessibility Nutrition Label recommendation**

**App version evaluated:** [version or "Current build"]
**Scope reviewed:** [common tasks / screens evaluated]

**You could claim:**
- [labels where every common task is ✅ or —]

**Why you could claim them:**
- [label]: [brief reason tied to completed common-task coverage]

**You should not claim:**
- [labels blocked by any ❌]
- [labels that are not applicable]

**Why you should not claim them:**
- [label]: [blocked task or why the label is not applicable]

**Common-task verification**
| Common Task | VoiceOver | Voice Control | Larger Text | Dark Mode | No Color | Contrast | Motion | Captions | Audio Desc |
|---|---|---|---|---|---|---|---|---|---|
| [task] | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — |

**Recommendation summary**
- You could claim: [labels]
- You should not claim: [labels]
Do not say "claim" without qualification. Phrase the output as a recommendation based on the reviewed scope. Do not suggest a label if any common task in that column is ❌. Use
only when the label is genuinely not applicable to that app or flow.
references/nutrition-labels.md
— 包含所有9个类别的官方通过/失败标准
当用户要求准备或起草App Store无障碍营养标签建议时,使用以下格式输出:
**无障碍营养标签建议**

**评估的应用版本:** [版本号或"当前构建版本"]
**审核范围:** [评估的常见任务/界面]

**可申报的类别:**
- [所有常见任务均为✅或—的类别]

**可申报的原因:**
- [类别]:[与已完成的常见任务覆盖范围相关的简要理由]

**不可申报的类别:**
- [存在任何❌的类别]
- [不适用的类别]

**不可申报的原因:**
- [类别]:[阻塞的任务或类别不适用的原因]

**常见任务验证**
| 常见任务 | VoiceOver | Voice Control | 大字体 | 深色模式 | 无颜色 | 对比度 | 动态效果 | 字幕 | 音频描述 |
|---|---|---|---|---|---|---|---|---|---|
| [任务] | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — | ✅ / ❌ / — |

**建议总结**
- 可申报:[类别]
- 不可申报:[类别]
不要无限制地说"可申报"。应基于审核范围输出建议。 如果该列中任何常见任务为❌,则不要建议申报该类别。仅当类别确实不适用于该应用或流程时使用

Accessibility Summary

无障碍摘要

Append after all code generation and fix tasks (modes 1, 2), unless the user explicitly requests code-only output. No preamble.
**Accessibility applied:**
- [one bullet per pattern added — e.g. "`.accessibilityLabel` on icon-only Share button"]

**Verify in Xcode:**
- Use Canvas **Dynamic Type Variants** (grid icon → Dynamic Type Variants) to check layout at all text sizes
- Use Canvas **Color Scheme Variants** to check light and dark mode
- Use **Accessibility Inspector** (Xcode → Open Developer Tool) Settings tab to simulate Increase Contrast, Reduce Motion, Bold Text on the Simulator

**If Xcode is unavailable:**
- Run equivalent checks with platform accessibility inspector tools and manual setting toggles (Dynamic Type, Contrast, Reduce Motion, VoiceOver/Voice Control)

**Test on device:**
- [relevant items from Must Test on Device checklist]
Omit "Accessibility applied" entirely if nothing was added (all native controls). Omit "Nutrition Label readiness" unless the user asked about it.
在所有代码生成和修复任务之后附加此摘要(工作流程模式1和2),除非用户明确要求仅输出代码。无需开场白。
**已应用的无障碍设计:**
- [每个添加的模式对应一个项目符号 — 例如"仅图标的分享按钮添加`.accessibilityLabel`"]

**在Xcode中验证:**
- 使用Canvas的**动态类型变体**(网格图标→动态类型变体)检查所有文本尺寸下的布局
- 使用Canvas的**颜色方案变体**检查浅色和深色模式
- 使用**无障碍检查器**(Xcode→打开开发者工具)的设置标签页,在模拟器上模拟增强对比度、减少动态效果、粗体文本

**如果无法使用Xcode:**
- 使用平台无障碍检查器工具和手动设置切换(动态类型、对比度、减少动态效果、VoiceOver/Voice Control)执行等效检查

**在设备上测试:**
- [来自设备必测清单的相关项]
如果未添加任何内容(全部为原生控件),则完全省略"已应用的无障碍设计"部分。 除非用户询问,否则省略"营养标签准备情况"部分。

Audit Output Format

审核输出格式

Only when user explicitly requests an audit. Never during code generation or fixes.
🔴 Blocks Assistive Tech — completely unreachable, fix immediately 🟡 Degrades Experience — reachable but significant friction 🟠 Incomplete Support — gaps preventing Nutrition Label claims ✅ Verified in code — confirmed correct by static analysis
Close with:
Must test on device: relevant items from the Review Checklist. Nutrition Label readiness: Achievable / Blocked by [issue] / Not applicable.
仅当用户明确要求审核时使用。代码生成或修复过程中切勿使用。
🔴 阻塞辅助技术 — 完全无法访问,立即修复 🟡 降低体验 — 可访问但存在显著障碍 🟠 支持不完整 — 存在影响营养标签申报的缺口 ✅ 代码中已验证 — 通过静态分析确认正确
结尾添加:
必须在设备上测试:来自审核清单的相关项。 营养标签准备情况:可实现 / 被[问题]阻塞 / 不适用。

Core Guidelines

核心准则

Principles

原则

  • Identify framework and platform first. SwiftUI and UIKit have different APIs; using the wrong one causes silent failures.
  • Every modifier needs a semantic reason. Adding
    .accessibilityLabel
    to a
    Button
    with visible text actually hurts — it overrides the text VoiceOver would read automatically.
  • Gate iOS 17+ APIs with
    #available
    .
    Version-specific APIs crash on older OS without availability checks.
  • Mark inferred labels with
    [VERIFY]
    .
    SF Symbol names (e.g.
    square.and.arrow.up
    ) rarely match what users expect to hear ("Share"). Inferred labels need human review.
  • Don't change core UI semantics or layout based on
    UIAccessibility.isVoiceOverRunning
    .
    Adapt to the actual user need by checking the relevant accessibility setting directly. Narrow coordination exceptions are fine, such as avoiding overlapping speech or extending transient timeouts while assistive tech is active.
  • Nutrition Labels require complete flow coverage. Claiming "VoiceOver supported" means every user flow works — login, onboarding, purchase, settings — not just the main screen.
  • Test contrast in both light and dark mode. A color pair that passes WCAG 4.5:1 in light mode often fails in dark mode due to different background values.
  • 首先确定框架和平台。SwiftUI和UIKit有不同的API;使用错误的API会导致静默失败。
  • 每个修饰符都需要语义上的理由。为带可见文本的
    Button
    添加
    .accessibilityLabel
    实际上会产生负面影响——它会覆盖VoiceOver原本会自动读取的文本。
  • 使用
    #available
    兼容iOS 17+ API
    。如果没有版本兼容判断,特定版本的API在旧系统上会崩溃。
  • [VERIFY]
    标记推断的标签
    。SF Symbol名称(例如
    square.and.arrow.up
    )很少与用户期望听到的内容("分享")匹配。推断的标签需要人工审核。
  • 不要根据
    UIAccessibility.isVoiceOverRunning
    更改核心UI语义或布局
    。通过直接检查相关的无障碍设置来适应用户的实际需求。狭窄的协调例外是可以的,例如避免重叠语音或在辅助技术激活时延长临时超时。
  • 营养标签需要完整的流程覆盖。申报"支持VoiceOver"意味着所有用户流程都能正常工作——登录、引导、购买、设置——而不仅仅是主界面。
  • 在浅色和深色模式下测试对比度。在浅色模式下符合WCAG 4.5:1的颜色组合,在深色模式下由于背景值不同,通常会不符合要求。

VoiceOver

VoiceOver

  • Every non-decorative element needs a concise, context-independent label
  • Icon-only buttons need
    .accessibilityLabel
    — blank is never acceptable
  • Decorative images:
    .accessibilityHidden(true)
  • State is a trait, not a label:
    .accessibilityAddTraits(.isSelected)
    not
    "Selected photo"
  • Group related elements:
    .accessibilityElement(children: .combine)
  • Announce dynamic changes: iOS 17+
    AccessibilityNotification.Announcement("Upload complete").post()
    , fallback
    UIAccessibility.post(notification: .announcement, argument: "Upload complete")
  • Deep reference →
    references/voiceover-swiftui.md
    or
    references/voiceover-uikit.md
  • 每个非装饰性元素都需要简洁、独立于上下文的标签
  • 仅图标的按钮需要
    .accessibilityLabel
    ——空白绝对不可接受
  • 装饰性图片:
    .accessibilityHidden(true)
  • 状态通过特征表示,而非标签:使用
    .accessibilityAddTraits(.isSelected)
    而非
    "Selected photo"
  • 相关元素分组:
    .accessibilityElement(children: .combine)
  • 动态变更公告:iOS 17+使用
    AccessibilityNotification.Announcement("上传完成").post()
    ,旧版本回退到
    UIAccessibility.post(notification: .announcement, argument: "上传完成")
  • 详细参考 →
    references/voiceover-swiftui.md
    references/voiceover-uikit.md

Voice Control

Voice Control

  • Labels must exactly match visible text — mismatches silently break "Tap [name]"
  • .accessibilityInputLabels(["Compose", "New Message"])
    for icon-only elements
  • Every interactive element must appear in "Show numbers" and "Show names" overlays
  • Hidden-on-swipe UI needs a voice-accessible alternative (
    .accessibilityAction
    )
  • Deep reference →
    references/voice-control.md
  • 标签必须与可见文本完全匹配——不匹配会导致"Tap [名称]"功能静默失效
  • 仅图标元素使用
    .accessibilityInputLabels(["Compose", "New Message"])
  • 每个交互元素必须出现在"显示数字"和"显示名称"覆盖层中
  • 滑动隐藏的UI需要语音可访问的替代方案(
    .accessibilityAction
  • 详细参考 →
    references/voice-control.md

Dynamic Type

Dynamic Type

  • Text styles only:
    .font(.body)
    not
    .font(.system(size: 16))
  • Scale custom values:
    @ScaledMetric(relativeTo: .body) var spacing: CGFloat = 8
  • Fixed-size UI chrome:
    .accessibilityShowsLargeContentViewer()
  • Adaptive layout: prefer
    ViewThatFits
    (iOS 16+) over manual
    dynamicTypeSize
    checks — it automatically picks the layout that fits
  • Deep reference →
    references/dynamic-type.md
  • 仅使用文本样式:
    .font(.body)
    而非
    .font(.system(size: 16))
  • 缩放自定义值:
    @ScaledMetric(relativeTo: .body) var spacing: CGFloat = 8
  • 固定尺寸的UI边框:
    .accessibilityShowsLargeContentViewer()
  • 自适应布局:优先使用
    ViewThatFits
    (iOS 16+)而非手动
    dynamicTypeSize
    检查——它会自动选择合适的布局
  • 详细参考 →
    references/dynamic-type.md

Display Settings

显示设置

  • Reduce Motion: replace meaningful animations with dissolve/fade; remove decorative ones
  • Contrast: semantic colors (
    Color(.label)
    ); WCAG 4.5:1 text, 3:1 non-text
  • Differentiate Without Color: add shape/icon/text alongside color
  • Reduce Transparency: replace
    .ultraThinMaterial
    with opaque when enabled
  • Deep reference →
    references/display-settings.md
  • 减少动态效果:有意义的动画替换为溶解/淡入淡出;移除装饰性动画
  • 对比度:使用语义颜色(
    Color(.label)
    );文本符合WCAG 4.5:1,非文本符合3:1
  • 无颜色区分:在颜色之外添加形状/图标/文本
  • 减少透明度:启用时将
    .ultraThinMaterial
    替换为不透明样式
  • 详细参考 →
    references/display-settings.md

Semantic Structure

语义结构

  • Reading order:
    .accessibilitySortPriority(_:)
    (higher = read first)
  • Focus on new screen: post
    .screenChanged
    notification
  • Modal focus:
    accessibilityViewIsModal = true
  • Custom navigation:
    accessibilityRotor(_:entries:)
  • Deep reference →
    references/semantic-structure.md
  • 阅读顺序:
    .accessibilitySortPriority(_:)
    (值越高越先读取)
  • 新界面焦点:推送
    .screenChanged
    通知
  • 模态焦点:
    accessibilityViewIsModal = true
  • 自定义导航:
    accessibilityRotor(_:entries:)
  • 详细参考 →
    references/semantic-structure.md

Motor / Input

操作/输入

  • Touch targets: minimum 44×44pt
  • Keyboard: every element via Tab, every modal via Escape
  • Switch Control:
    UIAccessibilityCustomAction
    for swipe-only gestures
  • Deep reference →
    references/motor-input.md
  • 触摸目标:最小44×44pt
  • 键盘:所有元素可通过Tab访问,所有模态可通过Escape关闭
  • Switch Control:
    UIAccessibilityCustomAction
    用于仅支持滑动的手势
  • 详细参考 →
    references/motor-input.md

Quick Reference

快速参考

SwiftUI Modifiers

SwiftUI修饰符

ModifierPurpose
.accessibilityLabel(_:)
VoiceOver text for non-text elements
.accessibilityHint(_:)
Brief result description
.accessibilityValue(_:)
Current value (sliders, progress)
.accessibilityHidden(true)
Hide decorative elements
.accessibilityAddTraits(_:)
Semantic role or state
.accessibilityRemoveTraits(_:)
Remove inherited trait
.accessibilityElement(children:)
.combine
/
.contain
/
.ignore
.accessibilitySortPriority(_:)
Reading order (higher = earlier)
.accessibilityAction(_:_:)
Named custom action
.accessibilityAdjustableAction(_:)
Increment/decrement
.accessibilityInputLabels(_:)
Voice Control alternate names
.accessibilityFocused(_:)
Programmatic focus
.accessibilityRotor(_:entries:)
Custom VoiceOver rotor
.accessibilityRepresentation(_:)
Replace AX tree for custom controls
.accessibilityIgnoresInvertColors(true)
Protect images in Smart Invert
.accessibilityShowsLargeContentViewer()
Large Content Viewer for fixed-size UI
修饰符用途
.accessibilityLabel(_:)
非文本元素的VoiceOver文本
.accessibilityHint(_:)
简要的结果描述
.accessibilityValue(_:)
当前值(滑块、进度条)
.accessibilityHidden(true)
隐藏装饰性元素
.accessibilityAddTraits(_:)
语义角色或状态
.accessibilityRemoveTraits(_:)
移除继承的特征
.accessibilityElement(children:)
.combine
/
.contain
/
.ignore
.accessibilitySortPriority(_:)
阅读顺序(值越高越靠前)
.accessibilityAction(_:_:)
命名的自定义操作
.accessibilityAdjustableAction(_:)
递增/递减
.accessibilityInputLabels(_:)
Voice Control替代名称
.accessibilityFocused(_:)
程序化焦点
.accessibilityRotor(_:entries:)
自定义VoiceOver转子
.accessibilityRepresentation(_:)
替换自定义控件的AX树
.accessibilityIgnoresInvertColors(true)
在智能反转中保护图片
.accessibilityShowsLargeContentViewer()
固定尺寸UI的大内容查看器

@Environment Values

@Environment值

ValuePurpose
\.accessibilityReduceMotion
Gate animations
\.accessibilityReduceTransparency
Replace blur effects
\.accessibilityDifferentiateWithoutColor
Add non-color indicators
\.colorSchemeContrast
.standard
/
.increased
\.dynamicTypeSize
Current text size
用途
\\.accessibilityReduceMotion
动态效果开关
\\.accessibilityReduceTransparency
替换模糊效果
\\.accessibilityDifferentiateWithoutColor
添加非颜色指示器
\\.colorSchemeContrast
.standard
/
.increased
\\.dynamicTypeSize
当前文本尺寸

Nutrition Labels → APIs

营养标签 → API

LabelKey APIsReference
VoiceOver
accessibilityLabel
, traits, actions, rotors
voiceover-swiftui.md
,
voiceover-uikit.md
Voice Control
accessibilityInputLabels
, visible text match
voice-control.md
Larger Text
@ScaledMetric
, text styles, Large Content Viewer
dynamic-type.md
Dark Interface
colorScheme
, semantic colors
display-settings.md
Differentiate Without Colorshapes + color
display-settings.md
Sufficient ContrastWCAG 4.5:1 text / 3:1 non-text
display-settings.md
Reduced Motion
accessibilityReduceMotion
, animation gate
display-settings.md
Captions
AVPlayerViewController
media-accessibility.md
Audio Descriptions
AVMediaCharacteristic.describesVideoForAccessibility
media-accessibility.md
标签关键API参考
VoiceOver
accessibilityLabel
、特征、操作、转子
voiceover-swiftui.md
voiceover-uikit.md
Voice Control
accessibilityInputLabels
、与可见文本匹配
voice-control.md
大字体
@ScaledMetric
、文本样式、大内容查看器
dynamic-type.md
深色界面
colorScheme
、语义颜色
display-settings.md
无颜色区分形状+颜色
display-settings.md
足够对比度WCAG 4.5:1文本 / 3:1非文本
display-settings.md
减少动态效果
accessibilityReduceMotion
、动态效果开关
display-settings.md
字幕
AVPlayerViewController
media-accessibility.md
音频描述
AVMediaCharacteristic.describesVideoForAccessibility
media-accessibility.md

Review Checklist

审核清单

Verifiable in Code

可在代码中验证的项

  • Icon-only buttons have
    .accessibilityLabel
  • Decorative images have
    .accessibilityHidden(true)
  • State expressed as traits, not labels
  • No hardcoded font sizes — text styles or
    @ScaledMetric
  • Animations gated on
    accessibilityReduceMotion
  • Semantic colors (not hardcoded hex)
  • .accessibilityInputLabels
    on icon-only elements
  • Touch targets ≥ 44×44pt
  • Modals use
    .sheet()
    or
    accessibilityViewIsModal
  • Swipe-only actions have
    .accessibilityAction
    alternatives
  • AVPlayerViewController
    for video
  • Photos/maps/video have
    .accessibilityIgnoresInvertColors()
  • XCUITest includes
    performAccessibilityAudit()
    with
    #available
    guards (iOS 17+ / macOS 14+), plus fallback assertions on older OS versions
  • 仅图标的按钮带有
    .accessibilityLabel
  • 装饰性图片带有
    .accessibilityHidden(true)
  • 状态通过特征而非标签表达
  • 无硬编码字体尺寸——使用文本样式或
    @ScaledMetric
  • 动态效果通过
    accessibilityReduceMotion
    开关控制
  • 使用语义颜色(而非硬编码十六进制值)
  • 仅图标元素带有
    .accessibilityInputLabels
  • 触摸目标≥44×44pt
  • 模态使用
    .sheet()
    accessibilityViewIsModal
  • 仅支持滑动的操作带有
    .accessibilityAction
    替代方案
  • 视频使用
    AVPlayerViewController
  • 照片/地图/视频带有
    .accessibilityIgnoresInvertColors()
  • XCUITest包含带
    #available
    判断的
    performAccessibilityAudit()
    (iOS 17+ / macOS 14+),旧系统版本使用回退断言

Must Test on Device

必须在设备上测试的项

  • VoiceOver: navigation order, reading flow, focus after push/modal
  • Voice Control: "Show numbers" coverage, "Tap [name]" activation
  • Switch Control: scanning path, custom actions reachable
  • Full Keyboard Access: Tab order, Escape dismissal
  • Dynamic Type: layout at max size — no clipping or overlap
  • Reduce Motion: all animations verified
  • Grayscale filter: information comprehensible without color
  • Dark + Increase Contrast: contrast in both modes
  • Captions and Audio Descriptions: auto-enable
Full testing procedures →
references/testing-auditing.md
  • VoiceOver:导航顺序、阅读流程、推送/模态后的焦点
  • Voice Control:"显示数字"覆盖范围、"Tap [名称]"激活
  • Switch Control:扫描路径、自定义操作可访问性
  • 全键盘访问:Tab顺序、Escape关闭
  • 动态类型:最大尺寸下的布局——无裁剪或重叠
  • 减少动态效果:所有动态效果已验证
  • 灰度滤镜:无需颜色即可理解信息
  • 深色+增强对比度:两种模式下的对比度
  • 字幕和音频描述:自动启用
完整测试流程 →
references/testing-auditing.md

Triage Playbook

分类处理手册

Blocks Assistive Tech — fix immediately

阻塞辅助技术 — 立即修复

  • Icon-only button has no label →
    references/voiceover-swiftui.md
  • Image missing alt text →
    references/voiceover-swiftui.md
  • Custom view not in accessibility tree →
    references/voiceover-uikit.md
  • VoiceOver loops or can't exit element →
    references/semantic-structure.md
  • 仅图标的按钮无标签 →
    references/voiceover-swiftui.md
  • 图片缺少替代文本 →
    references/voiceover-swiftui.md
  • 自定义视图未出现在无障碍树中 →
    references/voiceover-uikit.md
  • VoiceOver循环或无法退出元素 →
    references/semantic-structure.md

Degrades Experience — significant friction

降低体验 — 显著障碍

  • Voice Control misses an element →
    references/voice-control.md
  • Voice label doesn't match visible text →
    references/voice-control.md
  • Touch target < 44×44pt →
    references/motor-input.md
  • Color is the only differentiator →
    references/display-settings.md
  • Wrong reading order →
    references/semantic-structure.md
  • Modal doesn't trap focus →
    references/semantic-structure.md
  • Voice Control遗漏元素 →
    references/voice-control.md
  • 语音标签与可见文本不匹配 →
    references/voice-control.md
  • 触摸目标<44×44pt →
    references/motor-input.md
  • 仅使用颜色区分信息 →
    references/display-settings.md
  • 阅读顺序错误 →
    references/semantic-structure.md
  • 模态未捕获焦点 →
    references/semantic-structure.md

Incomplete Support — blocks Nutrition Label claims

支持不完整 — 阻塞营养标签申报

  • Text doesn't scale with Dynamic Type →
    references/dynamic-type.md
  • Animations ignore Reduce Motion →
    references/display-settings.md
  • Low contrast in dark mode →
    references/display-settings.md
  • No captions or audio descriptions →
    references/media-accessibility.md
  • Platform not accessible →
    references/platform-specifics.md
  • Nutrition Label preparation →
    references/nutrition-labels.md
  • 文本未随Dynamic Type缩放 →
    references/dynamic-type.md
  • 动画未遵循减少动态效果设置 →
    references/display-settings.md
  • 深色模式下对比度低 →
    references/display-settings.md
  • 无字幕或音频描述 →
    references/media-accessibility.md
  • 平台无障碍性不足 →
    references/platform-specifics.md
  • 营养标签准备 →
    references/nutrition-labels.md

Troubleshooting

故障排除

Wrong framework APIs applied

应用了错误的框架API

Symptom: SwiftUI modifiers used in UIKit/AppKit code, or platform APIs mixed across frameworks. Fix: Identify framework from imports (
import SwiftUI
,
import UIKit
,
import AppKit
) before applying APIs. SwiftUI uses modifiers, UIKit uses
UIAccessibility
properties, and AppKit uses
NSAccessibility
APIs.
症状: 在UIKit/AppKit代码中使用SwiftUI修饰符,或跨框架混合使用平台API。 修复: 在应用API之前,根据导入语句(
import SwiftUI
import UIKit
import AppKit
)确定框架。SwiftUI使用修饰符,UIKit使用
UIAccessibility
属性,AppKit使用
NSAccessibility
API。

Over-labeling native controls

原生控件过度添加标签

Symptom:
.accessibilityLabel
added to a
Button("Save")
or
Toggle("Dark Mode")
that already has visible text. Fix: Do not add
.accessibilityLabel
when the control has visible text — it overrides the automatic label and can desync with what's on screen. Only add labels to icon-only or non-text elements.
症状: 为带可见文本的
Button("Save")
Toggle("Dark Mode")
添加
.accessibilityLabel
修复: 当控件带有可见文本时,不要添加
.accessibilityLabel
——它会覆盖VoiceOver自动读取的文本,可能导致与屏幕显示内容不同步。仅为仅图标或非文本元素添加标签。

API requires newer OS than project target

API要求的系统版本高于项目目标版本

Symptom: Code uses platform-versioned APIs (iOS/macOS/tvOS/watchOS/visionOS) without availability checks. Fix: Gate with
#available
for every target OS you support and use older equivalents when needed. Common substitutions:
  • AccessibilityNotification.Announcement("…").post()
    UIAccessibility.post(notification: .announcement, argument: "…")
  • performAccessibilityAudit()
    → manual XCTest assertions
  • ViewThatFits
    (iOS 16+) →
    @Environment(\.dynamicTypeSize)
    with manual layout switching
  • Prefer multi-platform guards when code is shared:
    if #available(iOS 17, macOS 14, tvOS 17, watchOS 10, visionOS 1, *) { ... }
症状: 代码使用特定平台版本的API(iOS/macOS/tvOS/watchOS/visionOS)但未添加版本兼容判断。 修复: 为所有支持的目标系统添加
#available
判断,并在需要时使用旧版本的等效API。常见替代方案:
  • AccessibilityNotification.Announcement("…").post()
    UIAccessibility.post(notification: .announcement, argument: "…")
  • performAccessibilityAudit()
    → 手动XCTest断言
  • ViewThatFits
    (iOS 16+) →
    @Environment(\\.dynamicTypeSize)
    + 手动布局切换
  • 共享代码时优先使用多平台判断:
    if #available(iOS 17, macOS 14, tvOS 17, watchOS 10, visionOS 1, *) { ... }

Accessibility Summary missing

缺少无障碍摘要

Symptom: Code generated without the "Accessibility applied" / "Test on device" summary block. Fix: Always append the Accessibility Summary after code generation and fix tasks (workflow modes 1 and 2). Omit only when no accessibility patterns were added (all native controls with visible text).
症状: 生成的代码未包含"已应用的无障碍设计" / "设备上测试"摘要块。 修复: 在代码生成和修复任务后始终附加无障碍摘要(工作流程模式1和2)。仅当未添加任何无障碍模式时(全部为带可见文本的原生控件)才省略。

[VERIFY] comments missing on inferred labels

推断的标签缺少[VERIFY]注释

Symptom:
.accessibilityLabel
derived from SF Symbol names or method names without a
// [VERIFY]
comment. Fix: Any label that was inferred (not provided by the user) must include
// [VERIFY] confirm label matches intent
. SF Symbol names like
square.and.arrow.up
rarely match what users expect to hear.
症状: 从SF Symbol名称或方法名称推导的
.accessibilityLabel
未添加
// [VERIFY]
注释。 修复: 任何推断的标签(非用户提供)必须包含
// [VERIFY] confirm label matches intent
。像
square.and.arrow.up
这样的SF Symbol名称很少与用户期望听到的内容匹配。

References

参考资料

  • references/voiceover-swiftui.md
    — SwiftUI accessibility modifiers, traits, actions, rotors, announcements
  • references/voiceover-uikit.md
    — UIAccessibility protocol, custom elements, containers, notifications
  • references/voice-control.md
    — Input labels, "Show numbers/names", voice-accessible alternatives
  • references/motor-input.md
    — Switch Control, Full Keyboard Access, AssistiveTouch, tvOS focus
  • references/dynamic-type.md
    — Dynamic Type, @ScaledMetric, Large Content Viewer, adaptive layouts
  • references/display-settings.md
    — Reduce Motion, Contrast, Dark Mode, Color, Transparency, Invert
  • references/semantic-structure.md
    — Grouping, reading order, focus management, rotors, modal focus
  • references/media-accessibility.md
    — Captions, Audio Descriptions, Speech synthesis, Charts
  • references/testing-auditing.md
    — Accessibility Inspector, Xcode Canvas Variants, XCTest,
    performAccessibilityAudit()
    , manual testing
  • references/nutrition-labels.md
    — All 9 Nutrition Labels with pass/fail criteria
  • references/wcag-mapping.md
    — WCAG 2.2 Level A/AA success criteria mapped to SwiftUI/UIKit/AppKit APIs
  • references/assistive-access.md
    — Assistive Access (iOS 17+), design principles, testing
  • references/platform-specifics.md
    — macOS, watchOS, tvOS, visionOS specifics
  • examples/before-after-swiftui.md
    — SwiftUI before/after transformations
  • examples/before-after-uikit.md
    — UIKit before/after transformations
  • examples/before-after-appkit.md
    — AppKit (macOS) before/after transformations
  • resources/audit-template.swift
    — Drop-in XCUITest file for automated accessibility auditing (iOS 17+)
  • resources/qa-checklist.md
    — Standalone QA checklist for manual testing (hand to testers)
  • references/voiceover-swiftui.md
    — SwiftUI无障碍修饰符、特征、操作、转子、公告
  • references/voiceover-uikit.md
    — UIAccessibility协议、自定义元素、容器、通知
  • references/voice-control.md
    — 输入标签、"显示数字/名称"、语音可访问的替代方案
  • references/motor-input.md
    — Switch Control、全键盘访问、AssistiveTouch、tvOS焦点
  • references/dynamic-type.md
    — Dynamic Type、@ScaledMetric、大内容查看器、自适应布局
  • references/display-settings.md
    — 减少动态效果、对比度、深色模式、颜色、透明度、反转
  • references/semantic-structure.md
    — 分组、阅读顺序、焦点管理、转子、模态焦点
  • references/media-accessibility.md
    — 字幕、音频描述、语音合成、图表
  • references/testing-auditing.md
    — 无障碍检查器、Xcode Canvas变体、XCTest、
    performAccessibilityAudit()
    、手动测试
  • references/nutrition-labels.md
    — 所有9个营养标签的通过/失败标准
  • references/wcag-mapping.md
    — WCAG 2.2 Level A/AA成功标准与SwiftUI/UIKit/AppKit API的映射
  • references/assistive-access.md
    — Assistive Access(iOS 17+)、设计原则、测试
  • references/platform-specifics.md
    — macOS、watchOS、tvOS、visionOS的特定内容
  • examples/before-after-swiftui.md
    — SwiftUI前后转换示例
  • examples/before-after-uikit.md
    — UIKit前后转换示例
  • examples/before-after-appkit.md
    — AppKit(macOS)前后转换示例
  • resources/audit-template.swift
    — 用于自动无障碍审核的XCUITest文件(iOS 17+)
  • resources/qa-checklist.md
    — 用于手动测试的独立QA清单(提供给测试人员)",