swift-accessibility-skill
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePlatform 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 because SF Symbol names don't always match the intended user-facing meaning.
// [VERIFY]| Situation | Required on first write |
|---|---|
| |
| Nothing extra — text is the label automatically |
| |
| |
| |
| Replace with |
| Color conveys state/status | Add shape, icon, or text alongside color |
| |
| Custom slider / toggle / stepper | |
| Async content change | Post announcement with availability guards ( |
System | Nothing extra — SwiftUI traps focus automatically (custom overlays still need focus management) |
| Use |
| Custom tappable view | |
| Any new SwiftUI view | Verify with Xcode Canvas Variants (see Accessibility Summary) |
| |
Custom | |
| AppKit modal/popup UI | Trap focus and ensure dismiss action is keyboard + VoiceOver reachable |
| Any new AppKit view/controller | Verify with Accessibility Inspector and full keyboard navigation |
Prefer native controls (, , , , , ) — they get full accessibility automatically. Custom interactive views require explicit work.
For AppKit, prefer native controls (, , , , ) before custom interaction.
ButtonToggleStepperSliderPickerTextFieldNSButtonNSPopUpButtonNSSliderNSSegmentedControlNSTextFieldNSViewExample — icon-only button:
swift
Button {
shareAction()
} label: {
Image(systemName: "square.and.arrow.up")
}
.accessibilityLabel("Share") // [VERIFY] confirm label matches intentExample — 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在初稿阶段就融入无障碍设计——切勿先编写基础元素再后期修补。后期补充无障碍设计难度更大,容易被遗漏,且效果远不如从一开始就构建到位。
除非模式非显而易见,否则不要添加内联注释。对推断出的标签标记,因为SF Symbol名称并不总是与用户预期的字面含义匹配。
// [VERIFY]| 场景 | 首次编写时必须添加 |
|---|---|
| 带 |
| 无需额外操作——文本会自动作为标签 |
| |
| |
| |
| 替换为 |
| 颜色用于传达状态/状态信息 | 在颜色之外添加形状、图标或文本 |
非 | |
| 自定义滑块/开关/步进器 | |
| 异步内容变更 | 带版本兼容判断的公告推送(iOS 17+使用 |
系统 | 无需额外操作——SwiftUI会自动捕获焦点(自定义浮层仍需焦点管理) |
| 使用 |
| 自定义可点击视图 | |
| 任何新的SwiftUI视图 | 使用Xcode Canvas变体(查看无障碍摘要)进行验证 |
| 带 |
自定义 | |
| AppKit模态/弹窗UI | 捕获焦点并确保关闭操作可通过键盘和VoiceOver访问 |
| 任何新的AppKit视图/控制器 | 使用无障碍检查器和全键盘导航进行验证 |
优先使用原生控件(、、、、、)——它们会自动获得完整的无障碍支持。自定义交互视图需要显式配置。
对于AppKit,在自定义交互之前,优先使用原生控件(、、、、)。
ButtonToggleStepperSliderPickerTextFieldNSViewNSButtonNSPopUpButtonNSSliderNSSegmentedControlNSTextField示例 — 仅图标按钮:
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.mdWorkflow
工作流程
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 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).
#available应用初稿规则——在初稿阶段融入无障碍设计,无需注释。
对于iOS 15之后引入的API,始终添加版本兼容判断并提供旧系统的回退行为。
编写完成后,对照初稿规则表进行验证——输出前修复所有遗漏。
代码之后,附加无障碍摘要(见下文)。
#available2) Improve or fix existing code
2) 改进或修复现有代码
Apply fixes silently, no commentary.
For APIs introduced after iOS 15, always add 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.
#available- For transformation patterns → ,
examples/before-after-swiftui.md, orexamples/before-after-uikit.mdexamples/before-after-appkit.md - For platform issues →
references/platform-specifics.md
静默应用修复,无需注释。
对于iOS 15之后引入的API,始终添加版本兼容判断并提供旧系统的回退行为。
修复完成后,对照初稿规则表进行验证——输出前修复所有遗漏。
代码之后,附加无障碍摘要。
#available- 转换模式参考 → 、
examples/before-after-swiftui.md或examples/before-after-uikit.mdexamples/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) 准备营养标签建议
→ — all 9 categories with official pass/fail criteria
references/nutrition-labels.mdWhen 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.
—→ — 包含所有9个类别的官方通过/失败标准
references/nutrition-labels.md当用户要求准备或起草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 to a
.accessibilityLabelwith visible text actually hurts — it overrides the text VoiceOver would read automatically.Button - Gate iOS 17+ APIs with . Version-specific APIs crash on older OS without availability checks.
#available - Mark inferred labels with . SF Symbol names (e.g.
[VERIFY]) rarely match what users expect to hear ("Share"). Inferred labels need human review.square.and.arrow.up - Don't change core UI semantics or layout based on . 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.
UIAccessibility.isVoiceOverRunning - 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实际上会产生负面影响——它会覆盖VoiceOver原本会自动读取的文本。.accessibilityLabel - 使用兼容iOS 17+ API。如果没有版本兼容判断,特定版本的API在旧系统上会崩溃。
#available - 用标记推断的标签。SF Symbol名称(例如
[VERIFY])很少与用户期望听到的内容("分享")匹配。推断的标签需要人工审核。square.and.arrow.up - 不要根据更改核心UI语义或布局。通过直接检查相关的无障碍设置来适应用户的实际需求。狭窄的协调例外是可以的,例如避免重叠语音或在辅助技术激活时延长临时超时。
UIAccessibility.isVoiceOverRunning - 营养标签需要完整的流程覆盖。申报"支持VoiceOver"意味着所有用户流程都能正常工作——登录、引导、购买、设置——而不仅仅是主界面。
- 在浅色和深色模式下测试对比度。在浅色模式下符合WCAG 4.5:1的颜色组合,在深色模式下由于背景值不同,通常会不符合要求。
VoiceOver
VoiceOver
- Every non-decorative element needs a concise, context-independent label
- Icon-only buttons need — blank is never acceptable
.accessibilityLabel - Decorative images:
.accessibilityHidden(true) - State is a trait, not a label: not
.accessibilityAddTraits(.isSelected)"Selected photo" - Group related elements:
.accessibilityElement(children: .combine) - Announce dynamic changes: iOS 17+ , fallback
AccessibilityNotification.Announcement("Upload complete").post()UIAccessibility.post(notification: .announcement, argument: "Upload complete") - Deep reference → or
references/voiceover-swiftui.mdreferences/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.mdreferences/voiceover-uikit.md
Voice Control
Voice Control
- Labels must exactly match visible text — mismatches silently break "Tap [name]"
- for icon-only elements
.accessibilityInputLabels(["Compose", "New Message"]) - 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: not
.font(.body).font(.system(size: 16)) - Scale custom values:
@ScaledMetric(relativeTo: .body) var spacing: CGFloat = 8 - Fixed-size UI chrome:
.accessibilityShowsLargeContentViewer() - Adaptive layout: prefer (iOS 16+) over manual
ViewThatFitschecks — it automatically picks the layout that fitsdynamicTypeSize - Deep reference →
references/dynamic-type.md
- 仅使用文本样式:而非
.font(.body).font(.system(size: 16)) - 缩放自定义值:
@ScaledMetric(relativeTo: .body) var spacing: CGFloat = 8 - 固定尺寸的UI边框:
.accessibilityShowsLargeContentViewer() - 自适应布局:优先使用(iOS 16+)而非手动
ViewThatFits检查——它会自动选择合适的布局dynamicTypeSize - 详细参考 →
references/dynamic-type.md
Display Settings
显示设置
- Reduce Motion: replace meaningful animations with dissolve/fade; remove decorative ones
- Contrast: semantic colors (); WCAG 4.5:1 text, 3:1 non-text
Color(.label) - Differentiate Without Color: add shape/icon/text alongside color
- Reduce Transparency: replace with opaque when enabled
.ultraThinMaterial - Deep reference →
references/display-settings.md
- 减少动态效果:有意义的动画替换为溶解/淡入淡出;移除装饰性动画
- 对比度:使用语义颜色();文本符合WCAG 4.5:1,非文本符合3:1
Color(.label) - 无颜色区分:在颜色之外添加形状/图标/文本
- 减少透明度:启用时将替换为不透明样式
.ultraThinMaterial - 详细参考 →
references/display-settings.md
Semantic Structure
语义结构
- Reading order: (higher = read first)
.accessibilitySortPriority(_:) - Focus on new screen: post notification
.screenChanged - 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: for swipe-only gestures
UIAccessibilityCustomAction - Deep reference →
references/motor-input.md
- 触摸目标:最小44×44pt
- 键盘:所有元素可通过Tab访问,所有模态可通过Escape关闭
- Switch Control:用于仅支持滑动的手势
UIAccessibilityCustomAction - 详细参考 →
references/motor-input.md
Quick Reference
快速参考
SwiftUI Modifiers
SwiftUI修饰符
| Modifier | Purpose |
|---|---|
| VoiceOver text for non-text elements |
| Brief result description |
| Current value (sliders, progress) |
| Hide decorative elements |
| Semantic role or state |
| Remove inherited trait |
| |
| Reading order (higher = earlier) |
| Named custom action |
| Increment/decrement |
| Voice Control alternate names |
| Programmatic focus |
| Custom VoiceOver rotor |
| Replace AX tree for custom controls |
| Protect images in Smart Invert |
| Large Content Viewer for fixed-size UI |
| 修饰符 | 用途 |
|---|---|
| 非文本元素的VoiceOver文本 |
| 简要的结果描述 |
| 当前值(滑块、进度条) |
| 隐藏装饰性元素 |
| 语义角色或状态 |
| 移除继承的特征 |
| |
| 阅读顺序(值越高越靠前) |
| 命名的自定义操作 |
| 递增/递减 |
| Voice Control替代名称 |
| 程序化焦点 |
| 自定义VoiceOver转子 |
| 替换自定义控件的AX树 |
| 在智能反转中保护图片 |
| 固定尺寸UI的大内容查看器 |
@Environment Values
@Environment值
| Value | Purpose |
|---|---|
| Gate animations |
| Replace blur effects |
| Add non-color indicators |
| |
| Current text size |
| 值 | 用途 |
|---|---|
| 动态效果开关 |
| 替换模糊效果 |
| 添加非颜色指示器 |
| |
| 当前文本尺寸 |
Nutrition Labels → APIs
营养标签 → API
| Label | Key APIs | Reference |
|---|---|---|
| VoiceOver | | |
| Voice Control | | |
| Larger Text | | |
| Dark Interface | | |
| Differentiate Without Color | shapes + color | |
| Sufficient Contrast | WCAG 4.5:1 text / 3:1 non-text | |
| Reduced Motion | | |
| Captions | | |
| Audio Descriptions | | |
| 标签 | 关键API | 参考 |
|---|---|---|
| VoiceOver | | |
| Voice Control | | |
| 大字体 | | |
| 深色界面 | | |
| 无颜色区分 | 形状+颜色 | |
| 足够对比度 | WCAG 4.5:1文本 / 3:1非文本 | |
| 减少动态效果 | | |
| 字幕 | | |
| 音频描述 | | |
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)
- on icon-only elements
.accessibilityInputLabels - Touch targets ≥ 44×44pt
- Modals use or
.sheet()accessibilityViewIsModal - Swipe-only actions have alternatives
.accessibilityAction - for video
AVPlayerViewController - Photos/maps/video have
.accessibilityIgnoresInvertColors() - XCUITest includes with
performAccessibilityAudit()guards (iOS 17+ / macOS 14+), plus fallback assertions on older OS versions#available
- 仅图标的按钮带有
.accessibilityLabel - 装饰性图片带有
.accessibilityHidden(true) - 状态通过特征而非标签表达
- 无硬编码字体尺寸——使用文本样式或
@ScaledMetric - 动态效果通过开关控制
accessibilityReduceMotion - 使用语义颜色(而非硬编码十六进制值)
- 仅图标元素带有
.accessibilityInputLabels - 触摸目标≥44×44pt
- 模态使用或
.sheet()accessibilityViewIsModal - 仅支持滑动的操作带有替代方案
.accessibilityAction - 视频使用
AVPlayerViewController - 照片/地图/视频带有
.accessibilityIgnoresInvertColors() - XCUITest包含带判断的
#available(iOS 17+ / macOS 14+),旧系统版本使用回退断言performAccessibilityAudit()
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.mdTriage 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 (, , ) before applying APIs. SwiftUI uses modifiers, UIKit uses properties, and AppKit uses APIs.
import SwiftUIimport UIKitimport AppKitUIAccessibilityNSAccessibility症状: 在UIKit/AppKit代码中使用SwiftUI修饰符,或跨框架混合使用平台API。
修复: 在应用API之前,根据导入语句(、、)确定框架。SwiftUI使用修饰符,UIKit使用属性,AppKit使用API。
import SwiftUIimport UIKitimport AppKitUIAccessibilityNSAccessibilityOver-labeling native controls
原生控件过度添加标签
Symptom: added to a or that already has visible text.
Fix: Do not add 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.
.accessibilityLabelButton("Save")Toggle("Dark Mode").accessibilityLabel症状: 为带可见文本的或添加。
修复: 当控件带有可见文本时,不要添加——它会覆盖VoiceOver自动读取的文本,可能导致与屏幕显示内容不同步。仅为仅图标或非文本元素添加标签。
Button("Save")Toggle("Dark Mode").accessibilityLabel.accessibilityLabelAPI requires newer OS than project target
API要求的系统版本高于项目目标版本
Symptom: Code uses platform-versioned APIs (iOS/macOS/tvOS/watchOS/visionOS) without availability checks.
Fix: Gate with for every target OS you support and use older equivalents when needed. Common substitutions:
#available- →
AccessibilityNotification.Announcement("…").post()UIAccessibility.post(notification: .announcement, argument: "…") - → manual XCTest assertions
performAccessibilityAudit() - (iOS 16+) →
ViewThatFitswith manual layout switching@Environment(\.dynamicTypeSize) - 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)但未添加版本兼容判断。
修复: 为所有支持的目标系统添加判断,并在需要时使用旧版本的等效API。常见替代方案:
#available- →
AccessibilityNotification.Announcement("…").post()UIAccessibility.post(notification: .announcement, argument: "…") - → 手动XCTest断言
performAccessibilityAudit() - (iOS 16+) →
ViewThatFits+ 手动布局切换@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: derived from SF Symbol names or method names without a comment.
Fix: Any label that was inferred (not provided by the user) must include . SF Symbol names like rarely match what users expect to hear.
.accessibilityLabel// [VERIFY]// [VERIFY] confirm label matches intentsquare.and.arrow.up症状: 从SF Symbol名称或方法名称推导的未添加注释。
修复: 任何推断的标签(非用户提供)必须包含。像这样的SF Symbol名称很少与用户期望听到的内容匹配。
.accessibilityLabel// [VERIFY]// [VERIFY] confirm label matches intentsquare.and.arrow.upReferences
参考资料
- — SwiftUI accessibility modifiers, traits, actions, rotors, announcements
references/voiceover-swiftui.md - — UIAccessibility protocol, custom elements, containers, notifications
references/voiceover-uikit.md - — Input labels, "Show numbers/names", voice-accessible alternatives
references/voice-control.md - — Switch Control, Full Keyboard Access, AssistiveTouch, tvOS focus
references/motor-input.md - — Dynamic Type, @ScaledMetric, Large Content Viewer, adaptive layouts
references/dynamic-type.md - — Reduce Motion, Contrast, Dark Mode, Color, Transparency, Invert
references/display-settings.md - — Grouping, reading order, focus management, rotors, modal focus
references/semantic-structure.md - — Captions, Audio Descriptions, Speech synthesis, Charts
references/media-accessibility.md - — Accessibility Inspector, Xcode Canvas Variants, XCTest,
references/testing-auditing.md, manual testingperformAccessibilityAudit() - — All 9 Nutrition Labels with pass/fail criteria
references/nutrition-labels.md - — WCAG 2.2 Level A/AA success criteria mapped to SwiftUI/UIKit/AppKit APIs
references/wcag-mapping.md - — Assistive Access (iOS 17+), design principles, testing
references/assistive-access.md - — macOS, watchOS, tvOS, visionOS specifics
references/platform-specifics.md - — SwiftUI before/after transformations
examples/before-after-swiftui.md - — UIKit before/after transformations
examples/before-after-uikit.md - — AppKit (macOS) before/after transformations
examples/before-after-appkit.md - — Drop-in XCUITest file for automated accessibility auditing (iOS 17+)
resources/audit-template.swift - — Standalone QA checklist for manual testing (hand to testers)
resources/qa-checklist.md
- — SwiftUI无障碍修饰符、特征、操作、转子、公告
references/voiceover-swiftui.md - — UIAccessibility协议、自定义元素、容器、通知
references/voiceover-uikit.md - — 输入标签、"显示数字/名称"、语音可访问的替代方案
references/voice-control.md - — Switch Control、全键盘访问、AssistiveTouch、tvOS焦点
references/motor-input.md - — Dynamic Type、@ScaledMetric、大内容查看器、自适应布局
references/dynamic-type.md - — 减少动态效果、对比度、深色模式、颜色、透明度、反转
references/display-settings.md - — 分组、阅读顺序、焦点管理、转子、模态焦点
references/semantic-structure.md - — 字幕、音频描述、语音合成、图表
references/media-accessibility.md - — 无障碍检查器、Xcode Canvas变体、XCTest、
references/testing-auditing.md、手动测试performAccessibilityAudit() - — 所有9个营养标签的通过/失败标准
references/nutrition-labels.md - — WCAG 2.2 Level A/AA成功标准与SwiftUI/UIKit/AppKit API的映射
references/wcag-mapping.md - — Assistive Access(iOS 17+)、设计原则、测试
references/assistive-access.md - — macOS、watchOS、tvOS、visionOS的特定内容
references/platform-specifics.md - — SwiftUI前后转换示例
examples/before-after-swiftui.md - — UIKit前后转换示例
examples/before-after-uikit.md - — AppKit(macOS)前后转换示例
examples/before-after-appkit.md - — 用于自动无障碍审核的XCUITest文件(iOS 17+)
resources/audit-template.swift - — 用于手动测试的独立QA清单(提供给测试人员)",
resources/qa-checklist.md