swiftui-performance
SKILL.md
SwiftUI Performance
Comprehensive guide for diagnosing and fixing performance issues in SwiftUI apps. Based on Apple's Xcode performance documentation covering responsiveness, hangs, hitches, launch time, and terminations.
Issue Decision Tree
Start here to identify what type of performance problem you're dealing with:
Is the app unresponsive to touch/input?
├─ YES → HANG (main thread blocked >250ms)
│ See references/hangs-responsiveness.md
│
├─ NO, but scrolling/animations stutter?
│ → HITCH (frame delivered late)
│ See references/hitches-rendering.md
│
├─ NO, but app takes too long to appear?
│ → SLOW LAUNCH
│ See references/launch-terminations.md
│
├─ NO, but app gets killed by system?
│ → TERMINATION (OOM, watchdog, background timeout)
│ See references/launch-terminations.md
│
└─ NO, but views redraw too often / UI feels sluggish?
→ SWIFTUI VIEW PERFORMANCE
See references/swiftui-views.md
Key Metrics
| Issue | Metric | Target | Tool |
|---|---|---|---|
| Hang | Main thread block duration | <250ms | Time Profiler, MetricKit |
| Hitch | Hitch time ratio (ms/s) | <5 ms/s | Hitches instrument |
| Launch | Time to first frame (cold) | <400ms | App Launch template |
| Frame | Render time per frame | <16ms (60fps) / <8ms (120fps) | Core Animation instrument |
| Memory | Background footprint | <50MB | Allocations instrument |
| Redraws | Body invocation count | Minimize per interaction | SwiftUI instrument |
Quick Patterns
Move work off main thread
// Use .task for async work — suspends, never blocks
.task {
let result = await heavyOperation()
self.data = result // @MainActor auto-dispatch in SwiftUI
}
Prevent unnecessary view redraws
// Use @Observable (iOS 17+) for fine-grained invalidation
@Observable class Store {
var count = 0
var name = "" // changing name won't redraw views that only read count
}
Use lazy containers for large datasets
ScrollView {
LazyVStack { // only materializes visible views
ForEach(items) { item in ItemRow(item: item) }
}
}
Avoid AnyView type erasure
// Use @ViewBuilder instead — preserves structural identity
@ViewBuilder
func content(for state: State) -> some View {
switch state {
case .loading: ProgressView()
case .loaded(let data): DataView(data: data)
case .error(let err): ErrorView(error: err)
}
}
Defer non-critical launch work
func application(_ app: UIApplication, didFinishLaunchingWithOptions opts: ...) -> Bool {
setupCriticalUI() // only what's needed for first frame
DispatchQueue.global(qos: .utility).async { Analytics.configure() }
return true
}
Profiling Workflow
- Reproduce the issue on a physical device (Simulator hides real perf)
- Profile with Instruments (
Product → Profile)- Hangs → Time Profiler or System Trace
- Hitches → Animation Hitches template
- Redraws → SwiftUI template
- Launch → App Launch template
- Memory → Allocations + Leaks
- Identify the bottleneck (main thread work, expensive body, excessive redraws)
- Fix using patterns from reference docs
- Measure again — use XCTest performance metrics for regression testing
// XCTest scroll hitch measurement
func testScrollPerformance() {
let app = XCUIApplication()
app.launch()
measure(metrics: [XCTOSSignpostMetric.scrollDecelerationMetric]) {
app.tables.firstMatch.swipeUp()
}
}
Diagnostic Tools Reference
| Tool | What It Shows | When to Use |
|---|---|---|
| SwiftUI Instrument | Body invocations, attribute graph updates | Excessive redraws |
| Time Profiler | CPU usage per thread | Hangs, slow operations |
| System Trace | Thread states, waits, blocking | Lock contention, deadlocks |
| Hitches Instrument | Frame delivery timing | Scroll/animation jank |
| App Launch Template | dyld, static init, main thread phases | Slow startup |
| Allocations | Memory growth, leaks | OOM terminations |
| Xcode Organizer | Real-world metrics from shipped app | Field data analysis |
| MetricKit | Programmatic hang/hitch/launch/crash data | Production monitoring |
Reference Docs
Detailed guidance by topic:
references/swiftui-views.md— View identity, dependency tracking, @Observable, body optimizationreferences/hangs-responsiveness.md— Main thread blocking, async patterns, hang preventionreferences/hitches-rendering.md— Frame pipeline, commit vs render hitches, scroll performancereferences/launch-terminations.md— Launch phases, cold/warm start, OOM, watchdog killsreferences/diagnostic-tools.md— Instruments templates, MetricKit, XCTest metrics, os_signpost
Weekly Installs
1
Repository
benjaming/ai-skillsGitHub Stars
2
First Seen
14 days ago
Security Audits
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1