mcpField
S
swiftui-performance-audit

swiftui-performance-audit

github.com/steipete测试与质量7.4k181 次安装1 天前更新
代码仓库

关于 swiftui-performance-audit

用于审查 SwiftUI 性能的技能,覆盖代码检查、Instruments 跟踪分析、问题定位、修复建议和基线对比,面向排查视图卡顿的开发者。

主要功能

  1. 01从代码入手审查性能
  2. 02提供 Instruments 分析指引
  3. 03依据跟踪数据诊断
  4. 04提出针对性修复建议
  5. 05验证修复前后变化

适用场景

  1. 01查找视图反复失效问题
  2. 02排查列表滚动缓慢
  3. 03审查 body 中的高开销操作
  4. 04比较修复前后的性能

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/steipete/agent-scripts --skill swiftui-performance-audit

安装后在 Claude Code 中输入/swiftui-performance-audit确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
demystify-swiftui-performance-wwdc23.md
optimizing-swiftui-performance-instruments.md
understanding-hangs-in-your-app.md
understanding-improving-swiftui-performance.md

详细介绍

SwiftUI 性能审查

出处:转载自 @Dimillian 的 Dimillian/Skills(2025-12-31)。

概述

端到端审查 SwiftUI 视图性能,涵盖从性能检测和建立基线,到根本原因分析及具体修复步骤。

工作流决策树

  • 如果用户提供了代码,从“代码优先审查”开始。
  • 如果用户只描述了症状,请索要最少量的代码和上下文,然后进行“代码优先审查”。
  • 如果代码审查无法得出结论,则转到“引导用户进行性能分析”,并索要跟踪记录或截图。

1. 代码优先审查

收集:

  • 目标视图/功能的代码。
  • 数据流:状态、环境、可观察模型。
  • 症状和复现步骤。

重点关注:

  • 宽泛的状态变更导致视图失效风暴。
  • 列表中的身份不稳定(id 频繁变化、每次渲染都调用 UUID())。
  • body 中执行繁重操作(格式化、排序、图像解码)。
  • 布局抖动(深层堆栈、GeometryReader、偏好链)。
  • 未经降采样或调整尺寸的大图像。
  • 过度动画的视图层级(对大型视图树应用隐式动画)。

提供:

  • 可能的根本原因及代码引用。
  • 建议的修复方案和重构方法。
  • 如有需要,提供最小复现示例或性能检测建议。

2. 引导用户进行性能分析

说明如何使用 Instruments 收集数据:

  • 在 Instruments 中使用 SwiftUI 模板(Release 构建)。
  • 复现确切的交互操作(滚动、导航、动画)。
  • 采集 SwiftUI 时间线和 Time Profiler。
  • 导出相关轨道和调用树,或将其截图。

索要:

  • 跟踪记录导出文件,或 SwiftUI 轨道及 Time Profiler 调用树的截图。
  • 设备/OS/构建配置。

3. 分析并诊断

优先排查可能导致 SwiftUI 性能问题的因素:

  • 宽泛的状态变更导致视图失效风暴。
  • 列表中的身份不稳定(id 频繁变化、每次渲染都调用 UUID())。
  • body 中执行繁重操作(格式化、排序、图像解码)。
  • 布局抖动(深层堆栈、GeometryReader、偏好链)。
  • 未经降采样或调整尺寸的大图像。
  • 过度动画的视图层级(对大型视图树应用隐式动画)。

根据跟踪记录/日志中的证据总结发现。

4. 修复

应用有针对性的修复:

  • 缩小状态作用范围(将 @State/@Observable 放得更靠近叶视图)。
  • 为 ForEach 和列表保持身份稳定。
  • 将繁重操作移出 body(预计算、缓存、使用 @State)。
  • 对开销大的子树使用 equatable() 或值包装器。
  • 在渲染前对图像进行降采样。
  • 尽可能降低布局复杂度或使用固定尺寸。

常见代码异味(及修复方法)

代码审查时留意以下模式。

在 body 中使用开销大的格式化器
var body: some View {
    let number = NumberFormatter() // slow allocation
    let measure = MeasurementFormatter() // slow allocation
    Text(measure.string(from: .init(value: meters, unit: .meters)))
}

建议在模型或专用辅助工具中缓存格式化器:

final class DistanceFormatter {
    static let shared = DistanceFormatter()
    let number = NumberFormatter()
    let measure = MeasurementFormatter()
}
执行繁重操作的计算属性
var filtered: [Item] {
    items.filter { $0.isEnabled } // runs on every body eval
}

建议预先计算,或在变更时缓存:

@State private var filtered: [Item] = []
// update filtered when inputs change
在 body 或 ForEach 中排序/筛选
List {
    ForEach(items.sorted(by: sortRule)) { item in
        Row(item)
    }
}

建议在视图更新前只排序一次:

let sortedItems = items.sorted(by: sortRule)
在 ForEach 中内联筛选
ForEach(items.filter { $0.isEnabled }) { item in
    Row(item)
}

建议使用身份稳定的预筛选集合。

身份不稳定
ForEach(items, id: \.self) { item in
    Row(item)
}

避免对不稳定的值使用 id: \.self;请改用稳定 ID。

在主线程上解码图像
Image(uiImage: UIImage(data: data)!)

建议在主线程之外解码/降采样并存储结果。

可观察模型中的宽泛依赖
@Observable class Model {
    var items: [Item] = []
}

var body: some View {
    Row(isFavorite: model.items.contains(item))
}

建议使用粒度更细的视图模型或逐项状态,以减少更新扩散。

5. 验证

请用户重新进行相同的性能采集,并与基线指标进行比较。 如果用户提供了数据,请总结差异(CPU、掉帧、内存峰值)。

输出

提供:

  • 简短的指标表(如有数据,列出修复前后)。
  • 按影响排序的主要问题。
  • 建议的修复方案及预估工作量。

参考资料

用户提供 Apple 文档和 WWDC 资源后,将其添加到 references/ 目录下。

  • 使用 Instruments 优化 SwiftUI 性能:references/optimizing-swiftui-performance-instruments.md
  • 了解并改进 SwiftUI 性能:references/understanding-improving-swiftui-performance.md
  • 了解应用中的卡顿:references/understanding-hangs-in-your-app.md
  • 揭秘 SwiftUI 性能(WWDC23):references/demystify-swiftui-performance-wwdc23.md

评论

支持 Markdown