Loading...
Loading...
Diagnose SwiftUI performance issues including unnecessary re-renders, view identity problems, and slow body evaluations. Use when SwiftUI views are slow, janky, or re-rendering too often.
npx skill4agent add rshankras/claude-code-apple-skills swiftui-debuggingSelf._printChanges()@ObservableObservableObjectAnyViewWhat SwiftUI performance problem are you seeing?
|
+- Views re-render when they should not
| +- Read body-reevaluation.md
| +- Self._printChanges() to identify which property changed
| +- @Observable vs ObservableObject observation differences
| +- Splitting views to narrow observation scope
|
+- Scrolling is slow / choppy (lists, grids)
| +- Read lazy-loading.md
| +- VStack vs LazyVStack, ForEach without lazy container
| +- List prefetching, grid cell reuse
|
+- Views lose state unexpectedly / animate when they should not
| +- Read view-identity.md
| +- Structural vs explicit identity
| +- .id() misuse, conditional view branching
|
+- Known pitfall (AnyView, DateFormatter in body, etc.)
| +- Read common-pitfalls.md
| +- AnyView type erasure, object creation in body
| +- Over-observation, expensive computations
|
+- General "my SwiftUI app is slow" (unknown cause)
| +- Start with body-reevaluation.md, then common-pitfalls.md
| +- Use Instruments SwiftUI template (see Debugging Tools below)| API / Technique | Minimum Version | Reference |
|---|---|---|
| iOS 15 | body-reevaluation.md |
| iOS 17 / macOS 14 | body-reevaluation.md |
| iOS 13 | body-reevaluation.md |
| iOS 14 | lazy-loading.md |
| iOS 14 | lazy-loading.md |
| iOS 13 | view-identity.md |
| Instruments SwiftUI template | Xcode 14+ | SKILL.md |
| iOS 12 | SKILL.md |
| # | Mistake | Fix | Details |
|---|---|---|---|
| 1 | Large | Wrap in | lazy-loading.md |
| 2 | Using | Use | common-pitfalls.md |
| 3 | Creating objects in | Use | common-pitfalls.md |
| 4 | Observing entire model when only one property is needed | Split into smaller | body-reevaluation.md |
| 5 | Unstable | Use stable identifiers (database IDs, UUIDs), never array indices or random values | view-identity.md |
var body: some View {
let _ = Self._printChanges()
// ... view content
}ViewName: @self, @identity, _propertyName changed.import os
private let perfLog = OSLog(subsystem: "com.app.perf", category: "SwiftUI")
var body: some View {
let _ = os_signpost(.event, log: perfLog, name: "MyView.body")
// ... view content
}.id()ifelseForEach@ObservableObservableObject@StateLazyVStackLazyHStackVStackHStackList.frame(maxHeight: .infinity)AnyView@ViewBuilderGroupbodyDateFormatterNSPredicatetask { }Task.detachedAsyncImage.resizable()UIImage| File | Content |
|---|---|
| view-identity.md | Structural vs explicit identity, |
| body-reevaluation.md | What triggers body, |
| lazy-loading.md | Lazy vs eager containers, |
| common-pitfalls.md | |
| ../profiling/SKILL.md | General Instruments profiling (Time Profiler, Memory, Energy) |