From cc-mobile-ios
iOS performance patterns — Instruments tracing, SwiftUI `Self._printChanges()`, MetricKit, launch optimization, scroll smoothness, memory pressure, Signposts. Load when investigating jank, cold-start regressions, or shipping a release build.
How this skill is triggered — by the user, by Claude, or both
Slash command
/cc-mobile-ios:ios-performanceThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Any performance claim needs an Instruments trace, a MetricKit report, or a Signpost-annotated profile. No opinions in PR descriptions.
Any performance claim needs an Instruments trace, a MetricKit report, or a Signpost-annotated profile. No opinions in PR descriptions.
AppLauncher + didFinishLaunchingWithOptions executes on the main thread. Every synchronous thing here delays the first frame.Task.detached(priority: .utility) { ... } or wait for first scene if possible.TTFF (time to first frame) and TTI (time to interactive). The latter is the metric that actually matters.Pre-main contributions (dylib loading, objc init) show up in the App Launch template under "dylib loading" — cutting heavy Swift Package deps from the main target trims this.
struct OrderRow: View {
let order: Order
var body: some View {
let _ = Self._printChanges()
// ...
}
}
Log goes to the console when the body re-evaluates. Quietly remove before shipping.
@Observable macro automatically tracks per-property access — a view that reads vm.title only invalidates on title changes.LazyVStack / List for >50 rows; never ForEach inside a ScrollView for large sets.List(orders) { order in OrderRow(order: order) }
.listStyle(.plain)
Identifiable conformance is required. Use a stable id, not \.self on a value with equality quirks.
body should be cheap. Expensive work -> pre-computed in view model.AsyncImage with a contentMode: and explicit size. Prefer .task {} + a typed image pipeline if you need caching / transformations.GeometryReader in cells — it invalidates on every frame and tanks scroll..drawingGroup() for complex paths/effects that otherwise recompose every frame.UIImage(contentsOfFile:) loads lazily; UIImage(named:) keeps in the named cache. Explicitly release or reuse.Data arrays over 1MB should go through streams.self without a .sink(...) stored in cancellables leak quietly.weak captures in closures crossing async boundaries: prefer structured tasks (.task { ... }) so the lifecycle is tied to the view.import OSLog
private let logger = Logger(subsystem: "com.example.app", category: "orders")
private let signposter = OSSignposter(subsystem: "com.example.app", category: "orders")
func loadOrders() async throws {
let state = signposter.beginInterval("load-orders")
defer { signposter.endInterval("load-orders", state) }
// work...
}
Show up in Instruments' Points of Interest lane. Use short, stable names — they become column headers.
For production insights:
final class MetricSubscriber: NSObject, MXMetricManagerSubscriber {
func didReceive(_ payloads: [MXMetricPayload]) { /* upload */ }
func didReceive(_ payloads: [MXDiagnosticPayload]) { /* upload */ }
}
// In App init:
MXMetricManager.shared.add(MetricSubscriber())
Payloads arrive daily per device with launch times, hang rates, CPU/energy breakdowns. Ship to your analytics pipe.
await.URLSession.shared.data(for:) on the main actor if you can push it to an actor repo.DispatchSemaphore.wait() from the main thread.Record on a release build. Debug builds include non-optimized Swift and dylib validation overhead.
@State for values that live outside the view.onAppear { Task { ... } } where .task { ... } is the right tool.print(...) included).npx claudepluginhub dimitriremoiville/cc-mobile --plugin cc-mobile-iosSearches MemPalace before answering questions about past work, people, projects, or prior decisions. Returns verbatim stored content instead of guessing from model memory.
Guides Payload CMS config (payload.config.ts), collections, fields, hooks, access control, APIs. Debugs validation errors, security, relationships, queries, transactions, hook behavior.
Implements vector databases with Pinecone, Weaviate, Qdrant, Milvus, pgvector for semantic search, RAG, recommendations, and similarity systems. Optimizes embeddings, indexing, and hybrid search.