关于 axiom-ux-flow-audit
用于 iOS 用户体验审查的技能,检查用户能否完成流程、离开页面并理解应用状态;覆盖导航、空态与错误、无障碍和平台适配,并区分核心缺陷与情境检查。
主要功能
- 01识别流程死路和无法关闭的弹层
- 02检查主要操作隐藏及标签不匹配
- 03审查深层链接和空状态
- 04检查加载与错误反馈
- 05检查无障碍操作流程
- 06检查平台适配和引导流程
适用场景
- 01在 iOS 发布前审查导航流程
- 02发现无法退出或继续的页面
- 03检查深层链接和无结果体验
- 04检查异步反馈与 VoiceOver 可达性
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ charleswiltgen/ axiom --skill axiom-ux-flow-audit安装后在 Claude Code 中输入/axiom-ux-flow-audit确认已加载。
详细介绍
UX 流程审计
UX 问题不是表面瑕疵,而是会导致用户提交支持工单、给出差评并流失的缺陷。
Axiom 的代码级审计器会检查代码模式。这项技能检查用户的实际体验:他们能完成任务吗?能返回吗?知道正在发生什么吗?
6 项 iOS UX 原则(检测依据)
这些原则是每个检测类别的依据。违反原则时,用户会陷入困境、感到困惑或沮丧。
1. 信守承诺
按钮或标题所说的内容必须与用户实际得到的内容一致。点击“设置”按钮却打开个人资料页面,会破坏用户信任。
2. 保留退出途径
每个模态界面(sheet、fullScreenCover、alert)都必须提供退出方式。没有关闭按钮或下拉关闭手势的 sheet 会困住用户。
3. 让主要操作清晰可见
用户来此要做的主要事情必须一目了然,且可以直接点击。如果 CTA 需要滚动页面或翻找菜单,用户就找不到它。
4. 避免陷入死胡同
每个视图都必须提供前进路径(下一步)或完成状态(成功消息、返回起点)。没有操作也没有导航的视图就是死胡同。
5. 渐进式展示信息
不要让首屏信息过载。先展示必要内容,按需提供详细信息。若引导流程在第一页就列出 12 项设置,用户会流失。
6. 反馈闭环
异步操作期间,用户必须知道正在发生什么。没有加载状态 = “是不是坏了?”没有错误状态 = “哪里出错了?”没有空状态 = “这个功能是不是不存在?”
检测类别
8 项核心缺陷(始终检查——它们是 UX 缺陷,而非主观意见):
- 无路可走的视图(严重)
- 无法关闭的界面(严重)
- 隐藏过深的 CTA(高)
- 承诺与实际功能不符(高)
- 深层链接陷入死胡同(高)
- 缺少空状态(高)
- 缺少加载/错误状态(高)
- 无障碍访问陷入死胡同(高)
3 项情境检查(根据产品情境判断是否检查——这些涉及设计判断):
- 引导流程缺口(中)——需要了解产品的引导策略
- 数据路径中断(中)——与代码正确性问题有交集;仅在用户可感知到时纳入
- 平台一致性缺口(中)——取决于目标设备策略
核心缺陷总是值得报告。情境检查需要了解产品情况——如果看起来有问题,就标记出来,但也要说明这可能是有意为之。
1. 无路可走的视图(严重)
没有前进导航、没有操作,也没有完成状态的视图。
检测方法:
- SwiftUI:没有
NavigationLink、Button、.sheet、.fullScreenCover、.navigationDestination或关闭操作的视图 - UIKit:没有
IBAction、没有addTarget、没有导航推送/呈现调用,也没有UIBarButtonItem的视图控制器 - 检查作为导航目标但没有提供继续或返回方式的视图/VC
常见原因:开发期间的占位视图被一并发布到生产环境。
2. 无法关闭的界面(严重)
没有关闭路径的 sheet 或 fullScreenCover。
检测方法:
- SwiftUI:没有
@Environment(\.dismiss)或显式关闭按钮的.fullScreenCover;设置了.interactiveDismissDisabled(true)却没有其他关闭方式的.sheet;缺少取消操作的 alert/confirmation dialogs - UIKit:使用
present(_:animated:)且modalPresentationStyle = .fullScreen,但被呈现的 VC 没有关闭/返回按钮;设置了isModalInPresentation = true却没有其他关闭路径
为何严重:用户确实无法离开这个屏幕。唯一的退出方式是强制退出应用。
3. 隐藏的 CTA(高优先级)
主要操作隐藏在首屏以下、菜单中或导航后面。
检测:
- 主要操作按钮放在较长的
ScrollView内容之后 - 重要操作只存在于
.toolbar溢出菜单(.secondaryAction)中 - CTA 位于可展开的
DisclosureGroup区块内 - 主标签页的根视图中没有醒目的操作
不属于隐藏 CTA:有意放在首屏以下的内容,例如结账确认(“查看订单后再确认”)、条款接受(“阅读后再同意”),或用户应先看到再采取行动的内容。判断标准:首屏以下的布局是在帮助用户(他们需要先了解背景),还是在妨碍用户(他们找不到操作)?
4. 承诺与内容不匹配(高优先级)
导航标题、按钮标签或标签页名称与内容不符。
检测:
.navigationTitle("X"),但视图内容显然与 Y 有关NavigationLink("Settings")实际导航到个人资料或账户视图- 标签页标签与其内容不符
- 按钮文案暗示一种操作,实际执行的却是另一种操作
5. 深层链接无法继续操作(高优先级)
URL 能打开,但进入的是空白或损坏状态。
检测:
.onOpenURL处理程序推送视图时未检查数据是否存在- 深层链接目标假定数据已预先加载
- 通用链接处理未验证实体 ID
- 深层链接内容不可用时没有回退方案
交叉参考:axiom-swiftui-nav 涵盖深层链接架构。本类别检查 UX 结果。
6. 缺少空状态(高优先级)
列表、网格或内容视图没有数据时显示空白屏幕。
检测:
List或ForEach没有if items.isEmpty { ... }或用于空状态的.overlay- 显示
@Query结果时未检查是否为空 - 搜索结果没有“无结果”视图
- 筛选后的视图可能没有任何项目
7. 缺少加载/错误状态(高优先级)
异步操作没有反馈。
检测:
- SwiftUI:
.task { }或Task { }获取数据时没有加载指示器;使用try await却没有呈现错误(没有.alert或错误状态变量);状态枚举缺少.loading或.error情况 - UIKit:
URLSession调用没有UIActivityIndicatorView或进度界面;完成处理程序出错时不更新 UI;失败时缺少UIAlertController - 两者:网络调用没有超时或重试界面
- 两者:
catch区块只在#if DEBUG中执行print/记录日志,没有面向用户的反馈——用户看到的是操作悄无声息地失败
重点关注网络/写入操作:对于能在 100ms 内完成的快速本地读取(GRDB 查询、UserDefaults、缓存数据),跳过加载指示器——添加加载动画会造成视觉闪烁。重点关注网络调用、数据库写入以及任何可能实质性失败的操作。
系统性扫描:在某个文件中发现无提示错误模式时(例如,没有向用户反馈的 catch { print(...) }),请扫描所有类似文件,检查是否存在相同模式。单个 catch 区块问题通常表明整个代码库都存在这种习惯。
8. 无障碍操作无法继续(高优先级)
操作只能通过手势或视觉线索触达,辅助技术无法感知。
检测:
.onLongPressGesture/.swipeActions/DragGesture没有对应的.accessibilityAction- 自定义控件没有
.accessibilityLabel或.accessibilityHint - 导航仅依赖颜色(例如“点击绿色按钮”)
- 下拉刷新(
refreshable)没有 VoiceOver 可访问的替代方式(注意:refreshable自动支持无障碍;检查自定义实现)
交叉参考:axiom-accessibility-diag 涵盖完整的 WCAG 合规性。本类别专门检查辅助技术能否触达 UX 流程。
9. 引导流程缺陷(中)
首次启动流程不完整或令人不知所措。
检测:
- 没有由
@AppStorage控制的引导检查 - 引导流程没有跳过/稍后选项
- 引导界面超过 5 屏
- 在展示应用价值之前就要求用户创建账户
10. 数据路径错误(中)
状态/绑定连接问题导致用户体验问题(视图显示过时数据、编辑无法保存、存在数据但视图为空)。
检测:
- 非预览代码中的视图接受
@Binding,但初始化时使用了.constant() - 视图需要
@Environment值,但祖先视图未提供 - 应注入
@Observable模型,却在本地创建 - 应使用
@Binding向上传递更改,却使用了@State
范围说明:这与常规 SwiftUI 正确性(axiom-swiftui-debugging)存在重叠。只有在数据路径错误导致明显用户体验问题时,才在此处列出问题,例如空白屏幕、内容过时或编辑无法持久保存。属于代码审查范畴的编译器级或崩溃级问题应跳过。
11. 平台适配缺陷(中)
缺少 iPad 侧边栏、横屏显示异常、Mac Catalyst 问题。
检测:
NavigationStack没有针对 iPad 的NavigationSplitView替代方案- 没有使用
.horizontalSizeClass检查以适配布局 - 视图在横屏时显示异常(固定高度、无法滚动)
- iPad/Mac 缺少键盘快捷键支持
审查流程
步骤 1:梳理入口点
找出用户进入应用的所有方式:
@mainApp 结构体 / SceneDelegate.onOpenURL处理程序(深层链接)- Widget
Link目标 - 通知响应处理程序(
UNUserNotificationCenterDelegate) - Spotlight/Siri 意图处理程序
步骤 2:梳理导航容器
找出所有导航结构:
NavigationStack/NavigationSplitView- 带有标签页结构的
TabView .sheet/.fullScreenCover展示方式- 自定义模态展示方式
步骤 3:追踪流程
对于每个入口点 → 完成路径:
- 用户能否达成目标?
- 用户能否返回?
- 用户是否了解每个步骤中正在发生什么?
步骤 4:检查数据连接
@Binding变量是否确实由父视图传入?@Observable对象是否通过环境注入?- 是否处理了
@Query结果为空的情况?
步骤 5:检查平台适配性
- iPad:侧边栏/分栏视图是否正常工作?
- 横屏:布局是否适配?
- Mac Catalyst/为 iPad 设计:是否支持键盘快捷键?
步骤 6:检查无障碍流程
- VoiceOver 用户能否完成每个流程?
- 仅靠手势触发的操作是否也提供了无障碍操作?
跨审查器关联
当问题与其他 Axiom 审查器发现的问题重叠时,请注明关联并提高严重性:
| UX 问题 | 重叠的审查器 | 叠加影响 | 严重性提升 |
|---|---|---|---|
| 流程中断 + 缺少 NavigationPath | swiftui-nav-auditor | 无法通过编程方式修复 | 严重 |
仅靠手势触发的操作 + 没有 .accessibilityAction | accessibility-auditor | VoiceOver 用户无法继续 | 严重 |
| 缺少加载状态 + 未处理的异步错误 | concurrency-auditor | 崩溃 + 没有用户反馈 | 严重 |
缺少空状态 + @Query 没有结果 | swiftdata-auditor | 数据迁移后出现空白屏幕 | 高 |
| 深层链接无法继续 + 没有 URL 验证 | swiftui-nav-auditor | 外部链接触发静默失败 | 高 |
输出格式
增强评级表(针对严重和高严重性问题)
| 问题 | 紧急程度 | 影响范围 | 修复工作量 | ROI |
|---|---|---|---|---|
| 支付后流程中断 | 发布阻断项 | 所有用户 | 30 分钟 | 严重 |
| 搜索缺少空状态 | 下个版本 | 搜索用户 | 15 分钟 | 高 |
紧急程度:发布阻断项 / 下个版本 / 待办 影响范围:所有用户 / 特定流程 / 边缘情况 修复工作量:修复所需时间估算 ROI:根据紧急程度 × 影响范围 / 工作量计算
导航可达性评分
审计结束时,输出:
## Navigation Reachability
- Total screens found: [N] (views with navigation presentation)
- Deep-linkable screens: [N] (.onOpenURL can reach them)
- Widget-reachable screens: [N] (widget Link destinations)
- Notification-reachable screens: [N] (notification handlers)
- Coverage: [N]% of screens are externally reachable
修复工作量核查
大多数 UX 流程缺陷都能快速修复。有人说“这是个大改动”时,请查看此表:
| 缺陷 | 典型修复方式 | 时间 |
|---|---|---|
| 无法关闭的陷阱(没有关闭按钮) | 添加工具栏“取消”按钮 + dismiss() | 10-15 分钟 |
| 缺少空状态 | 添加 if items.isEmpty { ContentUnavailableView(...) } | 15-20 分钟 |
| CTA 难以发现(位置不当) | 将按钮从 .secondaryAction 移到 .primaryAction | 20-30 分钟 |
| 无法继续的视图(没有后续路径) | 添加 NavigationLink 或操作按钮 | 15-30 分钟 |
| 缺少加载状态 | 添加 @State var isLoading + ProgressView 覆盖层 | 15-20 分钟 |
| 静默错误(没有用户反馈) | 在 catch 代码块中添加 .alert 呈现 | 10-15 分钟 |
| 只能通过手势触发的操作 | 添加 .accessibilityAction + 可见的按钮替代方案 | 15-20 分钟 |
不修复的代价:付款后遇到无法关闭的陷阱或无法继续的页面,会在上线后的数小时内招致 1 星评价。抵消每条评价需要 10-20 条好评。花 15 分钟修复,可以避免数周的补救工作。
切勿自我安慰
| 想法 | 事实 |
|---|---|
| “UX 问题只是润色工作,以后再修” | UX 流程死胡同会招致 1 星评价。它们是缺陷,不是增强功能。现在花 15 分钟修复,可以避免数周的补救工作。 |
| “用户会自己弄明白” | 用户不会自己弄明白,他们会删除应用。用户平均只会尝试 30 秒。 |
| “上线后再添加空状态” | 空状态是新用户最先看到的内容。没有空状态就上线,意味着上线的产品有缺陷。 |
| “这个修复会造成很大的设计改动” | 大多数 UX 修复只是调整位置或状态(10-30 分钟)。请查看上方的修复工作量表。 |
| “无障碍功能是另一回事” | 如果 VoiceOver 用户无法完成某个流程,那就是死胡同。同一个缺陷,只是影响了不同用户。 |
| “这个屏幕只是临时的” | 临时屏幕也会随产品上线。也要检查它们。 |
| “有关闭手势就行了” | fullScreenCover 没有关闭手势。这正是陷阱所在。 |
资源
技能:axiom-swiftui-nav、axiom-accessibility-diag、axiom-hig、axiom-swiftui-debugging
Agent:ux-flow-auditor(自动扫描)、swiftui-nav-auditor(导航架构)、accessibility-auditor(WCAG 合规性)