Files
gh-glittercowboy-taches-cc-…/skills/expertise/iphone-apps/workflows/optimize-performance.md
2025-11-29 18:28:37 +08:00

2.0 KiB

Workflow: Optimize iOS App Performance

<required_reading> Read NOW:

  1. references/performance.md
  2. references/cli-observability.md </required_reading>
Measure first, optimize second. Never optimize based on assumptions. ## Step 1: Define the Problem

Ask:

  • What feels slow?
  • Startup? Scrolling? Specific action?
  • When did it start?

Step 2: Measure

CPU Profiling:

xcrun xctrace record \
  --template 'Time Profiler' \
  --device 'iPhone 16' \
  --attach AppName \
  --output profile.trace

Memory:

xcrun xctrace record --template 'Allocations' ...

Launch time:

# Add DYLD_PRINT_STATISTICS=1 to scheme environment

Step 3: Identify Bottlenecks

Look for:

  • Functions with high "self time"
  • Main thread blocking
  • Repeated expensive operations
  • Large allocations

SwiftUI re-renders:

var body: some View {
    let _ = Self._printChanges()
    // ...
}

Step 4: Common Optimizations

Main Thread

// Bad
let data = expensiveWork() // blocks UI

// Good
let data = await Task.detached { expensiveWork() }.value

SwiftUI

// Bad - rebuilds everything
struct BigView: View {
    @State var a, b, c, d, e
}

// Good - isolated state
struct BigView: View {
    var body: some View {
        SubViewA() // has own @State
        SubViewB() // has own @State
    }
}

Lists

// Use LazyVStack for long lists
ScrollView {
    LazyVStack {
        ForEach(items) { ... }
    }
}

Images

AsyncImage(url: url) { image in
    image.resizable()
} placeholder: {
    ProgressView()
}

Step 5: Measure Again

Did it improve? If not, revert.

Step 6: Performance Tests

func testScrollPerformance() {
    measure(metrics: [XCTCPUMetric(), XCTMemoryMetric()]) {
        // scroll simulation
    }
}
| Metric | Target | Unacceptable | |--------|--------|--------------| | Launch | < 1s | > 2s | | Scroll | 60 fps | < 30 fps | | Response | < 100ms | > 500ms |