Community编程与开发github.com

SwiftUI 专家技能

在编写、审查或重构 iOS/macOS 的 SwiftUI 代码时使用,涵盖状态与 `@Observable` 数据流、视图组合、可调整大小布局、安全区域、显示缩放、性能、列表、环境、本地化、动画、Liquid Glass 以及 API 迁移等主题。也适用于 iPhone Duo、可折叠或大屏布局(大屏上的 `NavigationSplitView`、iPhone 标签栏侧边栏、两栏重排、可折叠网格、`ArrangementView`、`ReservedRegion`)、铰链效果、竖直栏、`@State` 初始化或合成属性诊断、`@ContentBuilder` 歧义、可拖拽排序和拖放、自定义 `AsyncImage` 的 `URLSession`、列表之外的滑动操作、绑定到项的 `alert`/`confirmationDialog`、`ToolbarOverflowMenu`、`AnimatableValues`、Document API(`Document`/`DocumentReader`)以及 Instruments `.trace` 捕获与分析。

SwiftUI 专家技能 是什么?

这是一个面向 SwiftUI 开发者的专家级技能,旨在辅助编写、审查和优化 iOS/macOS 应用中的 SwiftUI 代码。该技能的核心价值在于提供一套全面的规则和检查清单,确保代码的正确性、性能和最佳实践,例如强制 `@State` 属性为 `private`、正确处理 `@Observable` 数据流、使用稳定的 `ForEach` 标识符,以及正确管理版本特定的 API 门控。它支持多种工作流,包括审查现有代码、实施新功能、以及通过 Instruments 进行性能分析和 trace 驱动改进,能够自动检测已弃用 API 并推荐现代替代方案。该技能内置了一个强大的主题路由器,涵盖状态管理、环境、视图组合、动画、布局(包括大屏和可折叠设备适配)、性能、图表、文档应用等数十个方面的详细指南,开发者可根据任务类型快速查阅对应的参考文档。此外,它还提供了详细的 Instruments trace 录制与分析流程,能够帮助开发者定位性能瓶颈,如挂起、SwiftUI 更新过度和动画丢帧,并给出具体的优化建议。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/erumkatzwan/agentic-product-starter/tree/HEAD/apps/ios/.agents/skills/swiftui-expert

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

SwiftUI 专家技能 是做什么的?

操作规则

  • 将每个 View 类型视为一个失效边界:仅赋予它需要读取的数据,并将频繁变化的依赖项保持在受影响的最小子树附近。
  • 在编写、审查或迁移 API 使用时,查阅 references/latest-apis.md;仅查找与任务相关的 API。
  • 将硬弃用的 API 替换为现代等效项。在功能开发期间,标记软弃用的 API 并保留原样(见 references/soft-deprecation.md)。
  • 除非必须桥接,否则优先使用原生 SwiftUI API 而非 UIKit/AppKit。
  • 关注正确性和性能;不强制执行特定架构(如 MVVM、VIPER 等)。
  • 鼓励将业务逻辑与视图分离以实现可测试性,但不强制规定方式。
  • 遵循 Apple 人机界面指南和 API 设计模式。
  • 仅在用户明确要求时才采用 Liquid Glass(见 references/liquid-glass.md)。
  • 将性能优化作为建议而非要求提出。
  • 对版本特定 API 使用 #available 门控并提供合理的回退方案。
  • 对于布局和渲染输入,读取最接近消耗该输入的 SwiftUI 视图的值;不要替代进程全局屏幕状态。

任务工作流

审查现有 SwiftUI 代码

  • 阅读待审查的代码,确定适用的主题。
  • 标记已弃用的 API(与 references/latest-apis.md 对比);替换硬弃用的 API,并标记软弃用的 API 而不重写,除非用户要求迁移。
  • 为每个相关主题运行下面的主题路由器。
  • 验证 #available 门控和版本特定功能的回退路径。
  • 对于大范围代码库审查,首先确定较小的关注区域并逐一呈现;如果用户请求全代码库审查,则将其拆分为待办事项列表。

改进现有 SwiftUI 代码

  • 对照主题路由器主题审查当前实现。
  • 用 references/latest-apis.md 中的现代等效项替换硬弃用的 API;在功能开发期间标记软弃用的 API 且不重写。
  • 重构热路径以减少不必要的状态更新。
  • 将复杂视图主体拆分为单独的子视图。
  • 当遇到 UIImage(data:) 时建议图像下采样(可选优化,见 references/image-optimization.md)。

实现新的 SwiftUI 功能

  • 首先设计数据流:识别拥有的状态与注入的状态。
  • 为最佳差异比较构建视图(尽早提取子视图)。
  • 应用正确的动画模式(隐式与显式、过渡)。
  • 对所有可点击元素使用 Button;添加无障碍分组和标签。
  • 使用 #available 门控版本特定 API 并提供回退方案。

录制新的 Instruments trace

当用户要求“录制 trace”、“对应用进行性能分析”、“捕获会话”等时触发。完整参考:references/trace-recording.md。

  1. 确认目标 — 附加到正在运行的应用、启动应用还是录制所有进程?如果用户未说明,请询问。必要时列出已连接的设备:
    python3 "${SKILL_DIR}/scripts/record_trace.py" --list-devices
    
  2. 根据目标类型选择模板 — SwiftUI 模板会在任意真实设备上填充 SwiftUI 通道:物理 iOS/iPadOS 设备或主机 Mac。唯一的例外是 iOS 模拟器,其中 SwiftUI 通道为空 — 在这种情况下切换为 --template "Time Profiler"(提供 Time Profiler + 挂起,但没有动画卡顿)。始终检查 --list-devices:simulators 类型 → Time Profiler;devices 类型(真实设备和主机 Mac)→ 默认 SwiftUI。完整决策表见 references/trace-recording.md。
  3. 开始录制。对于由代理驱动的会话(用户表示“完成后我会告诉你”),在后台启动并使用停止文件:
    python3 "${SKILL_DIR}/scripts/record_trace.py" \
        --device "<名称|udid>" --attach "<应用名称>" \
        --stop-file /tmp/stop-trace --output ~/Desktop/session.trace
    
    对于交互式会话,只需告知用户在完成后按 Ctrl+C。
  4. 发出停止信号 — 当用户表示已完成应用操作时,执行 touch /tmp/stop-trace 命令。脚本会干净地向 xctrace 发送 SIGINT 信号并等待最多 60 秒完成。
  5. 分析生成的 trace(流转到下面的“trace 驱动改进”工作流)。

Trace 驱动改进(提供了 Instruments .trace)

只要用户的请求引用了 .trace 文件就触发。目标 SwiftUI 源文件是可选的 — 如果提供了,则引用具体行号;如果没有,则根据 trace 已揭示的视图名称和符号推荐查看位置。

完整参考:references/trace-analysis.md。

**挂起:**如果 xctrace help 列出了 triage(Xcode 27.2 有此功能),则从 xctrace triage <trace> --style hangs 开始,然后使用 xctrace show 深入分析。集成的解析器仍然是处理卡顿、SwiftUI 更新、因果图以及日志或 signpost 窗口的工具。

解析器组合模式的摘要:

  1. **界定分析范围。**询问自己:用户想要整个 trace 还是一个片段?
    • “关注 X / 在 X 之后 / 在 X 与 Y 之间 / 在 X 期间” → 首先解析到一个时间窗口(见步骤 2)。
    • 没有范围提示 → 分析整个 trace。
  2. **解析时间窗口(仅在用户界定了范围时)。**解析器提供了两种发现模式:
    # 查找标记感兴趣区域开始/结束的日志:
    python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <路径> \
        --list-logs --log-message-contains "loaded feed" --log-limit 5
    # 或列出 os_signpost 区间(配对的开始/结束),可按名称过滤:
    python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <路径> \
        --list-signposts --signpost-name-contains "ImageDecode"
    
    两种模式都接受 --window START_MS:END_MS 来限定发现范围。选择与用户描述匹配的 time_ms(对于日志)或 start_ms/end_ms(对于 signpost)。构建如 --window 10400:11700 的时间窗口。
  3. 运行主要分析(带或不带 --window):
    python3 "${SKILL_DIR}/scripts/analyze_trace.py" --trace <路径> \
        --json-only --top 10 [--window START_MS:END_MS]
    
  4. 结合 references/trace-analysis.md 进行解读 — 关键诊断项:
    • 每个相关性中的 main_running_coverage_pct(<25% = 被阻塞;≥75% = CPU 密集型)。
    • swiftui-causes.top_sources 揭示了为什么更新持续发生 — 像 UserDefaultObserver.send() 或宽 EnvironmentWriter 条目这样的高边数源是结构性失效错误。修复其中一个通常能消除许多下游的热视图。
  5. **当某个特定视图显示为开销大时,询问是谁使其失效。**使用 --fanin-for "<视图名称>" 获取驱动更新的源节点的排序列表。
  6. **可选地关联源代码。**如果用户指向了一个文件,阅读该文件并将视图名称/用户代码符号与其中的标识符匹配。如果没有,根据 SwiftUI 报告的视图名称推荐应打开哪些文件。
  7. **返回一个优先级排序的计划。**引用证据(覆盖率百分比、热符号、重叠视图、日志时间戳、因果图边)并将每个建议路由到主题路由器参考。
  8. 仅当用户要求修改时才编辑代码。

主题路由器

针对当前任务相关的每个主题查阅对应的参考文件:

主题参考文件
状态管理references/state-management.md
环境和 @Entry,包括“在 '@Entry var' 中存储闭包/类类型”的警告references/environment-patterns.md
视图组合references/view-structure.md
视图修饰符和标识references/modifier-patterns.md
性能references/performance-patterns.md
列表和 ForEachreferences/list-patterns.md
可调整大小布局、安全区域、两栏重排、可折叠网格、排列和保留区域references/layout-best-practices.md
iPhone Duo、可折叠或大屏(先阅读以选择技术)references/iphone-duo.md
表单、导航、大屏上的 NavigationSplitView 以及标签栏/侧边栏(sidebarAdaptable)references/sheet-navigation-patterns.md
ScrollView、滚动位置和滚动几何references/scroll-patterns.md
焦点管理references/focus-patterns.md
动画(基础)references/animation-basics.md
动画(过渡)references/animation-transitions.md
动画(高级)references/animation-advanced.md
无障碍references/accessibility-patterns.md
Swift Chartsreferences/charts.md
Charts 无障碍references/charts-accessibility.md
图像优化和显示缩放references/image-optimization.md
工具栏references/toolbar-patterns.md
基于文档的应用references/document-apps.md
WebKitreferences/webkit-integration.md
富文本编辑references/styled-text-editing.md
Liquid Glass (iOS 26+)references/liquid-glass.md
macOS 场景references/macos-scenes.md
macOS 窗口样式references/macos-window-styling.md
macOS 视图references/macos-views.md
文本模式references/text-patterns.md
本地化references/localization.md
已弃用 API 查询references/latest-apis.md
处理软弃用 APIreferences/soft-deprecation.md
预览references/previews.md
Instruments trace 分析references/trace-analysis.md
Instruments trace 录制references/trace-recording.md

正确性检查清单

以下是硬性规则 — 违反即表示错误:

  • @State 属性为 private
  • @Binding 仅在子视图修改父视图状态时使用
  • 父视图拥有的输入不存储为 @State/@StateObject;有意的状态初始值需记录为一次性
  • @StateObject 用于视图拥有的对象;@ObservedObject 用于注入的对象
  • iOS 17+:@State 搭配 @Observable;@Bindable 用于需要绑定的可观察注入对象
  • ForEach 使用稳定的标识(绝不使用 .indices/\.offset;id 的生命周期超过视图,且不基于可变内容派生)
  • 每个 ForEach 元素的视图数量恒定;List 行是单元的
  • 自定义 @Environment/@FocusedValue 键中不存储闭包
  • 自定义 @Entry 的默认值是稳定的(不包含 Model()/Date()/UUID() 表达式)
  • SwiftUI 显示缩放来自 @Environment(\.displayScale),而非全局屏幕状态
  • 安全区域内容不重复应用 GeometryProxy.safeAreaInsets
  • .animation(_:value:) 始终包含 value 参数
  • @FocusState 属性为 private
  • 在 .focusable() 视图的点击手势处理器中没有冗余的 @FocusState 写入
  • 版本特定 API 使用 #available 门控并具有合理的回退方案
  • 使用图表类型的文件中包含 import Charts
  • 预览使用自包含的模拟数据;不依赖实时服务或网络

相关技能