mcpField
S
swiftui-performance

swiftui-performance

github.com/livsy90开发120118 次安装16 周前更新
代码仓库

关于 swiftui-performance

swiftui-performance 是用于审查和重构 SwiftUI 代码的技能,重点分析变更如何使视图失效并触发更新。它通过检查身份、状态、依赖、布局和生命周期,帮助开发者控制渲染工作的影响范围。

主要功能

  1. 01分析视图身份与状态归属
  2. 02查找 body 中的高开销工作
  3. 03检查宽泛的模型依赖
  4. 04审查列表、布局与绘制成本
  5. 05评估异步生命周期与取消
  6. 06提出针对性重构和验证方法

适用场景

  1. 01审查 SwiftUI 屏幕或列表
  2. 02减少不必要的视图更新
  3. 03调查滚动或动画卡顿
  4. 04验证 SwiftUI 性能假设

安装

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

$npx skills add https://github.com/livsy90/ios-performance-agent-skills --skill swiftui-performance

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

包含的文件

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

agents/
openai.yaml
references/
async-lifecycle-and-mainactor.md
body-cost-and-render-models.md
closures-bindings-and-equatable.md
identity-and-state.md
layout-drawing-and-animation.md
lists-pagination-and-rows.md
observation-and-dependencies.md
profiling-validation.md

详细介绍

SwiftUI 性能

目的

使用此技能,以优先考虑性能、关注变更局部性的思路审查和重构 SwiftUI 代码。

SwiftUI 性能优化应说明哪项变更会使界面的哪一部分失效、为何这项工作会产生影响,以及如何让更新保持局部化。

范围

在以下场景中使用此技能:

  • 审查 SwiftUI 屏幕、列表、行、布局、绘制、动画和生命周期
  • 通过有针对性的重构减少不必要的更新或渲染工作
  • 仅在用于验证 SwiftUI 性能假设时制定性能分析计划

在以下场景中不要使用此技能:

  • 仅涉及 UIKit 的性能问题
  • 应用启动性能问题,除非问题出在 SwiftUI 根视图或场景构建中
  • 网络、后端延迟、数据库性能或缓存问题,除非它们会影响 SwiftUI 更新
  • 不涉及 SwiftUI 代码路径的通用 Instruments 操作指南
  • 没有明确 SwiftUI 性能风险的大范围架构改写

核心模型

先回答以下三个问题:

  1. 哪些内容发生了变化?
  2. 哪些视图依赖这项变化?
  3. 这项变化会引发多少界面工作?

然后检查:

  • 标识:SwiftUI 是否会在更新期间保留同一个逻辑视图?
  • 生命周期:状态是否由需要它的最小稳定组件持有?
  • 依赖:每个视图是否只读取渲染所需的数据?
  • 渲染:body 是否开销小、行为可预测,且不包含繁重的转换工作?
  • 生命周期:异步工作是否由 .task、.onAppear 或显式操作触发,而不是从 body 启动?

SwiftUI 视图是对界面的值描述。不要将其视为 UIKit 风格的长生命周期对象。

审查工作流

在建议大范围改动之前,先检查最小相关代码路径。

按以下顺序检查:

  1. 稳定且有意设计的标识。
  2. body 中的高开销工作。
  3. 宽泛的状态或模型读取。
  4. 状态的所有权和生命周期。
  5. 列表、行和分页结构。
  6. 闭包较多的输入、自定义绑定和不必要的类型擦除。
  7. 重复内容中的布局、绘制和动画开销。
  8. 异步生命周期、取消和主线程隔离工作。
  9. 在有助于确认时进行性能分析或使用调试探针。

优先进行有针对性的重构,而非架构改写。

证据规则

始终区分:

  • 静态代码审查发现
  • 可能的风险
  • 假设
  • 测量结果
  • 用户提供的证据
  • 工具生成的证据

除非用户提供了证据,或确实运行了性能分析命令,否则绝不可编造耗时数据或声称已获得性能分析结果。

推荐表述:

这个父视图读取了整个模型,因此该模型发生变化时,屏幕的大部分区域都可能失效。

避免表述:

这会耗费 500 ms。

常见风险信号

如果以下模式出现在更新或滚动路径中,请指出:

  • 不稳定的 ID,例如 .id(UUID()) 或 var id: UUID { UUID() }
  • 对可变集合使用基于索引的标识
  • 在 body 中排序、筛选、分组、格式化、解析、解码或读取数据库
  • 在 ForEach 中筛选,而不是预先准备可见行
  • 将一个庞大的模型传给每个子视图
  • 隐藏了许多状态读取的宽泛计算属性
  • 在大型重复集合中使用 AnyView
  • 本可使用键路径绑定时,却使用自定义 Binding(get:set:)
  • 行视图中存储了许多非视觉闭包
  • 每一行都使用 GeometryReader、偏好项、重阴影、遮罩、模糊或叠加层
  • 直接从 body 启动异步工作
  • 在行内使用未设保护条件的 .onAppear 分页触发器

重构指南

使用能够解决根本原因的最小改动:

  • 保持身份稳定
  • 将开销大的转换移出 body
  • 在重复渲染路径之外准备好可直接用于渲染的模型
  • 将状态移近拥有它的组件
  • 将大型视图拆分为依赖关系明确的子视图
  • 简化行视图的输入和重复结构
  • 无需转换时,优先使用键路径绑定,而不是自定义闭包绑定
  • 仅当视觉相等性明确,且判断成本低于重新计算时,才使用 .equatable()
  • 当工作与变化的输入相关且应自动取消并重启时,使用 .task(id:)
  • 仅当确实需要更底层控制的高频路径时,才考虑使用 UIKit

不要将 .equatable()、记忆化或缓存作为一概而论的解决方案。先说明失效或渲染问题。

参考资料路由

仅在任务需要更多细节时阅读参考资料:

  • references/identity-and-state.md — 身份、.id、ForEach、@State、@StateObject、@ObservedObject、自有可观察模型
  • references/observation-and-dependencies.md — Observation、ObservableObject、宽泛依赖、环境读取
  • references/body-cost-and-render-models.md — 排序、筛选、格式化、派生数据、渲染模型
  • references/lists-pagination-and-rows.md — List、ScrollView、LazyVStack、行视图、分页、滚动
  • references/closures-bindings-and-equatable.md — 闭包、绑定、.equatable()、操作处理器
  • references/layout-drawing-and-animation.md — 布局、绘制、修饰符、动画卡顿
  • references/async-lifecycle-and-mainactor.md — .task、.onAppear、取消、MainActor
  • references/profiling-validation.md — Instruments、xctrace、signposts、XCTest、MetricKit

回复格式

对于代码评审,请按以下格式回答:

  1. 主要问题
  2. 该问题在 SwiftUI 中为何重要
  3. 风险级别
  4. 建议的重构
  5. 有帮助时提供代码示例
  6. 如需确认,应测量的内容

对于性能分析请求,请按以下格式回答:

  1. 场景
  2. 假设
  3. 工具或探针
  4. 需要关注的内容
  5. 如何比较优化前后的结果

回答要具体。不要笼统地说“SwiftUI 很慢”。请说明具体的身份、依赖、渲染、布局、绘制、动画或生命周期问题。

最终原则

当代码能清楚地体现变化的局部性时,SwiftUI 的性能就会有所提升。

评论

支持 Markdown