swift-performance

fusengine's avatarfrom fusengine

Optimize SwiftUI and Swift app performance with Instruments profiling, lazy loading, memory management, and view optimization. Use when diagnosing slow UI, fixing memory leaks, optimizing scroll performance, or reducing app launch time.

0stars🔀0forks📁View on GitHub🕐Updated Jan 10, 2026

When & Why to Use This Skill

This Claude skill provides expert guidance and actionable code patterns to optimize SwiftUI and Swift application performance. It focuses on diagnosing UI bottlenecks, eliminating memory leaks, and implementing efficient data handling to ensure a responsive and high-quality user experience through Instruments profiling and best-practice refactoring.

Use Cases

  • Diagnosing and resolving UI lag or 'jank' in complex lists by implementing LazyVStack and view-level caching techniques.
  • Detecting and fixing memory leaks or retain cycles in ViewModels using Instruments profiling and weak reference patterns.
  • Reducing app launch time by refactoring initialization logic and deferring non-critical background tasks using lazy initialization.
  • Optimizing SwiftUI view updates by utilizing Equatable protocols and granular state management to prevent redundant renders and CPU spikes.
nameswift-performance
descriptionOptimize SwiftUI and Swift app performance with Instruments profiling, lazy loading, memory management, and view optimization. Use when diagnosing slow UI, fixing memory leaks, optimizing scroll performance, or reducing app launch time.

Swift Performance Optimization

SwiftUI View Optimization

// ❌ BAD - Recreates formatter every render
struct BadView: View {
    var body: some View {
        Text(Date(), formatter: DateFormatter()) // New instance each time!
    }
}

// ✅ GOOD - Cached formatter
struct GoodView: View {
    private static let formatter: DateFormatter = {
        let f = DateFormatter()
        f.dateStyle = .medium
        return f
    }()

    var body: some View {
        Text(Date(), formatter: Self.formatter)
    }
}

// ✅ Use Equatable to prevent unnecessary updates
struct ItemView: View, Equatable {
    let item: Item

    static func == (lhs: Self, rhs: Self) -> Bool {
        lhs.item.id == rhs.item.id
    }

    var body: some View {
        Text(item.name)
    }
}

Lazy Loading

// ✅ LazyVStack for long lists
ScrollView {
    LazyVStack(spacing: 16) {
        ForEach(items) { item in
            ItemRow(item: item)
        }
    }
}

// ✅ LazyView wrapper for heavy views
struct LazyView<Content: View>: View {
    let build: () -> Content

    init(_ build: @autoclosure @escaping () -> Content) {
        self.build = build
    }

    var body: Content {
        build()
    }
}

// Usage - defers initialization
NavigationLink {
    LazyView(HeavyDetailView(item: item))
} label: {
    Text(item.name)
}

Memory Management

// ✅ Avoid retain cycles with weak references
class ViewModel: ObservableObject {
    private var cancellables = Set<AnyCancellable>()

    func observe() {
        NotificationCenter.default
            .publisher(for: .someNotification)
            .sink { [weak self] _ in
                self?.handleNotification()
            }
            .store(in: &cancellables)
    }
}

// ✅ Use value types when possible
struct User: Sendable {  // Struct, not class
    let id: UUID
    let name: String
}

// ✅ Image caching
actor ImageCache {
    private var cache = NSCache<NSString, UIImage>()

    func image(for url: URL) async -> UIImage? {
        let key = url.absoluteString as NSString
        if let cached = cache.object(forKey: key) {
            return cached
        }
        guard let image = await downloadImage(url) else { return nil }
        cache.setObject(image, forKey: key)
        return image
    }
}

Instruments Profiling

Instrument Detects
Time Profiler Slow functions, CPU usage
Allocations Memory growth, leaks
Leaks Retain cycles
SwiftUI View body updates, layout
Core Animation Offscreen renders, blending

Common Performance Issues

// ❌ Heavy computation in body
var body: some View {
    let sorted = items.sorted() // Runs every render!
    List(sorted) { ... }
}

// ✅ Move to ViewModel or cache
@Observable class ViewModel {
    var items: [Item] = [] {
        didSet { sortedItems = items.sorted() }
    }
    private(set) var sortedItems: [Item] = []
}

// ❌ Unnecessary state invalidation
@State private var allItems: [Item] = []  // Changes invalidate entire view

// ✅ Use @Observable with granular properties
@Observable class ItemsStore {
    var displayedItems: [Item] = []  // Only this triggers updates
    var metadata: Metadata = .empty   // Independent updates
}

Launch Time Optimization

// ✅ Defer non-essential work
@main
struct MyApp: App {
    init() {
        // Only critical initialization here
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
                .task {
                    // Defer analytics, caching, etc.
                    await DeferredSetup.run()
                }
        }
    }
}

// ✅ Use lazy initialization
class AppServices {
    static let shared = AppServices()
    lazy var analytics = AnalyticsService()  // Created on first use
    lazy var imageCache = ImageCache()
}
swift-performance – AI Agent Skills | Claude Skills