ios-performance/SKILL.md
Analyze and optimize iOS app performance, memory usage, and battery efficiency. Use when debugging slow UI, investigating memory leaks, profiling CPU usage, optimizing SwiftUI rendering, reducing app launch time, or fixing animation jank. Triggers on performance, slow, memory leak, CPU, battery, lag, jank, optimize, Instruments, profiling.
npx skillsauth add abanoub-ashraf/manus-skills-import ios-performanceInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are a performance specialist for iOS apps. When this skill activates, help identify and fix performance bottlenecks.
Always measure first! Don't guess at performance problems.
// Bad - Forces recreation on every parent update
ForEach(items.indices, id: \.self) { index in
ItemView(item: items[index])
}
// Good - Stable identity
ForEach(items, id: \.id) { item in
ItemView(item: item)
}
// Use Equatable conformance
struct ItemView: View, Equatable {
let item: Item
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.item.id == rhs.item.id &&
lhs.item.title == rhs.item.title
}
var body: some View {
// Only redraws when Equatable check fails
}
}
// Wrap in EquatableView
EquatableView(content: ItemView(item: item))
// Use LazyVStack/LazyHStack for long lists
ScrollView {
LazyVStack {
ForEach(items) { item in
ItemRow(item: item)
}
}
}
// Use LazyVGrid for grids
LazyVGrid(columns: columns) {
ForEach(items) { item in
GridItem(item: item)
}
}
struct ContentView: View {
@State private var loadTask: Task<Void, Never>?
var body: some View {
List { content }
.task {
// Automatically cancelled on disappear
await loadData()
}
.onDisappear {
// Cancel manual tasks
loadTask?.cancel()
}
}
}
// Common leak: Strong reference in closure
class ViewModel {
var onComplete: (() -> Void)?
func startTask() {
// Leak! Self is strongly captured
someService.fetch { result in
self.handleResult(result)
self.onComplete?()
}
}
// Fixed: Weak capture
func startTaskFixed() {
someService.fetch { [weak self] result in
guard let self else { return }
self.handleResult(result)
self.onComplete?()
}
}
}
# Profile with Leaks instrument
xcrun instruments -t "Leaks" -D /tmp/leaks.trace MyApp.app
# Profile with Allocations
xcrun instruments -t "Allocations" MyApp.app
In Xcode: Debug > Debug Memory Graph
// Downsampled loading for thumbnails
func downsampledImage(at url: URL, to pointSize: CGSize) -> UIImage? {
let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
guard let source = CGImageSourceCreateWithURL(url as CFURL, imageSourceOptions) else {
return nil
}
let maxDimensionInPixels = max(pointSize.width, pointSize.height) * UIScreen.main.scale
let downsampleOptions = [
kCGImageSourceCreateThumbnailFromImageAlways: true,
kCGImageSourceShouldCacheImmediately: true,
kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels
] as CFDictionary
guard let downsampledImage = CGImageSourceCreateThumbnailAtIndex(source, 0, downsampleOptions) else {
return nil
}
return UIImage(cgImage: downsampledImage)
}
AsyncImage(url: imageURL) { phase in
switch phase {
case .empty:
ProgressView()
case .success(let image):
image
.resizable()
.aspectRatio(contentMode: .fill)
case .failure:
Image(systemName: "photo")
@unknown default:
EmptyView()
}
}
.frame(width: 100, height: 100)
-dead_strip// Defer non-essential initialization
@main
struct MyApp: App {
init() {
// Only critical setup here
setupCrashReporting()
}
var body: some Scene {
WindowGroup {
ContentView()
.task {
// Defer non-critical work
await setupAnalytics()
await preloadCache()
}
}
}
}
# Add to scheme environment variables
DYLD_PRINT_STATISTICS=1
DYLD_PRINT_STATISTICS_DETAILS=1
// Batch requests when possible
func loadDashboard() async throws -> Dashboard {
async let profile = api.fetchProfile()
async let feed = api.fetchFeed()
async let notifications = api.fetchNotifications()
return Dashboard(
profile: try await profile,
feed: try await feed,
notifications: try await notifications
)
}
// Implement caching
actor ImageCache {
private var cache = NSCache<NSURL, UIImage>()
func image(for url: URL) async throws -> UIImage {
if let cached = cache.object(forKey: url as NSURL) {
return cached
}
let image = try await downloadImage(from: url)
cache.setObject(image, forKey: url as NSURL)
return image
}
}
// Use built-in animations (GPU accelerated)
withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) {
isExpanded.toggle()
}
// Avoid animating expensive properties
// Bad: Animating shadow (causes offscreen rendering)
.shadow(radius: isHovered ? 10 : 0)
// Better: Use opacity on a pre-rendered shadow
.background(
shadowView
.opacity(isHovered ? 1 : 0)
)
Canvas { context, size in
for point in dataPoints {
context.fill(
Path(ellipseIn: CGRect(origin: point, size: CGSize(width: 4, height: 4))),
with: .color(.blue)
)
}
}
# Time Profiler
xcrun instruments -t "Time Profiler" MyApp.app
# Core Animation (for UI performance)
xcrun instruments -t "Core Animation" MyApp.app
# Energy Log
xcrun instruments -t "Energy Log" MyApp.app
# System Trace (comprehensive)
xcrun instruments -t "System Trace" MyApp.app
## Performance Analysis Report
### Metrics
- Launch Time: X.Xs (target: <2s)
- Memory Peak: X MB
- CPU Average: X%
- Dropped Frames: X/minute
### Issues Found
1. **[Critical/Major/Minor]** - Description
- Location: file:line
- Impact: [Metric affected]
- Root Cause: [Analysis]
- Recommended Fix: [Code/approach]
### Optimization Opportunities
1. [Description with expected improvement]
development
Design principles for building polished, native-feeling SwiftUI apps and widgets. Use this skill when creating or modifying SwiftUI views, iOS widgets (WidgetKit), or any native Apple UI. Ensures proper spacing, typography, colors, and widget implementations that look and feel like quality apps rather than AI-generated slop.
data-ai
Design and implement SwiftUI views, components, and app architecture. Use when creating new SwiftUI views, implementing MVVM/TCA patterns, managing state with @Observable, @State, @Binding, or @Environment, designing navigation flows, or structuring iOS app architecture. Triggers on SwiftUI, view model, state management, navigation, coordinator pattern.
development
Implement, review, or improve SwiftUI animations and transitions. Use when adding implicit or explicit animations with withAnimation, configuring spring animations (.smooth, .snappy, .bouncy), building phase or keyframe animations with PhaseAnimator/KeyframeAnimator, creating hero transitions with matchedGeometryEffect or matchedTransitionSource, adding SF Symbol effects (bounce, pulse, variableColor, breathe, rotate, wiggle), implementing custom Transition or CustomAnimation types, or ensuring animations respect accessibilityReduceMotion.
testing
Audit SwiftUI views for accessibility (iOS + macOS) with patch-ready fixes