SwiftUI 可访问性内部

发布: (2025年12月27日 GMT+8 05:39)
5 min read
原文: Dev.to

Source: Dev.to

请提供您希望翻译的具体文本内容,我将为您翻译成简体中文并保持原有的格式、Markdown 语法以及技术术语不变。谢谢!

可访问性是平行视图树

SwiftUI 构建 两棵树

  • 视觉视图树
  • 可访问性树

它们相关——但 并不相同。单个视觉视图可以:

  • 暴露多个可访问性元素
  • 与兄弟视图合并
  • 完全隐藏
  • 动态更改角色

理解这一点可以解释大多数“为什么 VoiceOver 没有正确朗读?”的 bug。

SwiftUI 如何创建可访问性元素

默认情况下:

  • 大多数控件(ButtonToggleTextField)会自动生成可访问性元素。
  • 容器(HStackVStackZStack)通常 不会

示例

HStack {
    Image(systemName: "heart.fill")
    Text("Favorites")
}

VoiceOver 可能会朗读为:“heart fill, Favorites”,除非你另行指示 SwiftUI。

分组 vs 分离元素

SwiftUI 为您提供对分组的显式控制。

将子元素合并为一个元素

.accessibilityElement(children: .combine)

结果:“Favorites, button”

完全忽略子元素

.accessibilityElement(children: .ignore)

现在您需要手动定义所有内容。

将子元素分别包含(默认)

.accessibilityElement(children: .contain)

当每个子元素都有其自身含义时使用此方式。

角色、特征与语义

可访问性不仅仅是标签——它是意义。SwiftUI 使用特征来描述行为:

  • isButton
  • isHeader
  • isSelected
  • isDisabled

示例

Text("Settings")
    .accessibilityAddTraits(.isHeader)

现在 VoiceOver 能够理解层级,而不仅仅是文本。

焦点系统(对导航至关重要)

SwiftUI 的可访问性焦点是基于状态驱动的。

@AccessibilityFocusState var focused: Bool
Text("Error occurred")
    .accessibilityFocused($focused)

触发焦点:

focused = true

适用于以下情况:

  • 表单验证错误
  • 导航过渡
  • 警报和弹出页
  • 动态内容更新

如果没有焦点控制,用户会迷失方向。

状态更改与可访问性更新

SwiftUI 会在以下情况下自动朗读更改:

  • 文本更改
  • 值更新
  • 控件切换

自定义视图需要显式朗读:

UIAccessibility.post(
    notification: .announcement,
    argument: "Upload complete"
)

请谨慎使用——但要有意图地使用。

可访问性与 NavigationStack

导航会影响可访问性树。导航时:

  • 先前的元素被移除
  • 构建新的树
  • 除非手动控制,否则焦点会重置

导航后最佳实践:

.accessibilityFocused($focusOnTitle)

这与 UIKit 的 “screen changed” 行为相同。

手势 vs 可访问性操作

自定义手势默认不可访问。

不良示例

.onTapGesture { submit() }

VoiceOver 用户无法发现此手势。

正确示例

.accessibilityAction {
    submit()
}

或者使用真实的 Button

隐藏装饰性元素

装饰性视图应对辅助功能隐藏:

Image("background")
    .accessibilityHidden(true)

否则 VoiceOver 会朗读无意义的内容。

动态文字是布局问题

动态文字不仅仅是字体——它会影响布局。SwiftUI 会自动:

  • 增大字体大小
  • 重新排版文本
  • 调整行高

您的布局必须允许增长。

不良实践

  • 固定高度
  • 文本被裁剪
  • 僵硬的堆叠

良好实践

  • 灵活的框架
  • 多行文本
  • 自适应布局

正确测试可访问性

  • Simulator: VoiceOver, Dynamic Type, Reduce Motion, Increase Contrast
  • Xcode Accessibility Inspector: element order, labels, traits, hit targets

经验法则: 如果导航时感觉别扭 → 那可能就是问题所在。

可访问性设计规则(内部级别)

  • 可访问性是状态驱动的
  • 焦点是显式的
  • 语义比标签更重要
  • 自定义视图需要自定义可访问性
  • 导航会重置焦点,除非进行处理
  • 手势需要可访问性操作
  • 布局必须支持动态文字大小

最后思考

SwiftUI 可访问性并不是一个后加的功能。它是一个与以下各方面紧密结合的一流系统:

  • 渲染
  • 状态
  • 导航
  • 布局
  • 交互

当你从一开始就将可访问性纳入设计时:

  • 你的 UI 会更清晰
  • 你的架构会得到改进
  • 你的应用会更具 “Apple 风格”
  • 所有人都会受益 —— 不仅仅是使用辅助功能的用户
Back to Blog

相关文章

阅读更多 »

SwiftUI 焦点系统 & 键盘内部

!Sebastien Lato https://media2.dev.to/dynamic/image/width=50,height=50,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads...

SwiftUI 手势系统内部

markdown !Sebastien Latohttps://media2.dev.to/dynamic/image/width=50,height=50,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%...

ScrollView 与 SwiftUI 中的坐标空间

基于滚动的 UI 在现代应用中随处可见——collapsing headers、parallax effects、sticky toolbars、section pinning、scroll‑driven animations、pull‑to‑refresh……