Claude Agent Skill · by Affaan M

Swiftui Patterns

Install Swiftui Patterns skill for Claude Code from affaan-m/everything-claude-code.

Install
Terminal · npx
$npx skills add https://github.com/affaan-m/everything-claude-code --skill swiftui-patterns
Works with Paperclip

How Swiftui Patterns fits into a Paperclip company.

Swiftui Patterns drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md259 lines
Expand
---name: swiftui-patternsdescription: SwiftUI architecture patterns, state management with @Observable, view composition, navigation, performance optimization, and modern iOS/macOS UI best practices.--- # SwiftUI Patterns Modern SwiftUI patterns for building declarative, performant user interfaces on Apple platforms. Covers the Observation framework, view composition, type-safe navigation, and performance optimization. ## When to Activate - Building SwiftUI views and managing state (`@State`, `@Observable`, `@Binding`)- Designing navigation flows with `NavigationStack`- Structuring view models and data flow- Optimizing rendering performance for lists and complex layouts- Working with environment values and dependency injection in SwiftUI ## State Management ### Property Wrapper Selection Choose the simplest wrapper that fits: | Wrapper | Use Case ||---------|----------|| `@State` | View-local value types (toggles, form fields, sheet presentation) || `@Binding` | Two-way reference to parent's `@State` || `@Observable` class + `@State` | Owned model with multiple properties || `@Observable` class (no wrapper) | Read-only reference passed from parent || `@Bindable` | Two-way binding to an `@Observable` property || `@Environment` | Shared dependencies injected via `.environment()` | ### @Observable ViewModel Use `@Observable` (not `ObservableObject`) — it tracks property-level changes so SwiftUI only re-renders views that read the changed property: ```swift@Observablefinal class ItemListViewModel {    private(set) var items: [Item] = []    private(set) var isLoading = false    var searchText = ""     private let repository: any ItemRepository     init(repository: any ItemRepository = DefaultItemRepository()) {        self.repository = repository    }     func load() async {        isLoading = true        defer { isLoading = false }        items = (try? await repository.fetchAll()) ?? []    }}``` ### View Consuming the ViewModel ```swiftstruct ItemListView: View {    @State private var viewModel: ItemListViewModel     init(viewModel: ItemListViewModel = ItemListViewModel()) {        _viewModel = State(initialValue: viewModel)    }     var body: some View {        List(viewModel.items) { item in            ItemRow(item: item)        }        .searchable(text: $viewModel.searchText)        .overlay { if viewModel.isLoading { ProgressView() } }        .task { await viewModel.load() }    }}``` ### Environment Injection Replace `@EnvironmentObject` with `@Environment`: ```swift// InjectContentView()    .environment(authManager) // Consumestruct ProfileView: View {    @Environment(AuthManager.self) private var auth     var body: some View {        Text(auth.currentUser?.name ?? "Guest")    }}``` ## View Composition ### Extract Subviews to Limit Invalidation Break views into small, focused structs. When state changes, only the subview reading that state re-renders: ```swiftstruct OrderView: View {    @State private var viewModel = OrderViewModel()     var body: some View {        VStack {            OrderHeader(title: viewModel.title)            OrderItemList(items: viewModel.items)            OrderTotal(total: viewModel.total)        }    }}``` ### ViewModifier for Reusable Styling ```swiftstruct CardModifier: ViewModifier {    func body(content: Content) -> some View {        content            .padding()            .background(.regularMaterial)            .clipShape(RoundedRectangle(cornerRadius: 12))    }} extension View {    func cardStyle() -> some View {        modifier(CardModifier())    }}``` ## Navigation ### Type-Safe NavigationStack Use `NavigationStack` with `NavigationPath` for programmatic, type-safe routing: ```swift@Observablefinal class Router {    var path = NavigationPath()     func navigate(to destination: Destination) {        path.append(destination)    }     func popToRoot() {        path = NavigationPath()    }} enum Destination: Hashable {    case detail(Item.ID)    case settings    case profile(User.ID)} struct RootView: View {    @State private var router = Router()     var body: some View {        NavigationStack(path: $router.path) {            HomeView()                .navigationDestination(for: Destination.self) { dest in                    switch dest {                    case .detail(let id): ItemDetailView(itemID: id)                    case .settings: SettingsView()                    case .profile(let id): ProfileView(userID: id)                    }                }        }        .environment(router)    }}``` ## Performance ### Use Lazy Containers for Large Collections `LazyVStack` and `LazyHStack` create views only when visible: ```swiftScrollView {    LazyVStack(spacing: 8) {        ForEach(items) { item in            ItemRow(item: item)        }    }}``` ### Stable Identifiers Always use stable, unique IDs in `ForEach` — avoid using array indices: ```swift// Use Identifiable conformance or explicit idForEach(items, id: \.stableID) { item in    ItemRow(item: item)}``` ### Avoid Expensive Work in body - Never perform I/O, network calls, or heavy computation inside `body`- Use `.task {}` for async work — it cancels automatically when the view disappears- Use `.sensoryFeedback()` and `.geometryGroup()` sparingly in scroll views- Minimize `.shadow()`, `.blur()`, and `.mask()` in lists — they trigger offscreen rendering ### Equatable Conformance For views with expensive bodies, conform to `Equatable` to skip unnecessary re-renders: ```swiftstruct ExpensiveChartView: View, Equatable {    let dataPoints: [DataPoint] // DataPoint must conform to Equatable     static func == (lhs: Self, rhs: Self) -> Bool {        lhs.dataPoints == rhs.dataPoints    }     var body: some View {        // Complex chart rendering    }}``` ## Previews Use `#Preview` macro with inline mock data for fast iteration: ```swift#Preview("Empty state") {    ItemListView(viewModel: ItemListViewModel(repository: EmptyMockRepository()))} #Preview("Loaded") {    ItemListView(viewModel: ItemListViewModel(repository: PopulatedMockRepository()))}``` ## Anti-Patterns to Avoid - Using `ObservableObject` / `@Published` / `@StateObject` / `@EnvironmentObject` in new code — migrate to `@Observable`- Putting async work directly in `body` or `init` — use `.task {}` or explicit load methods- Creating view models as `@State` inside child views that don't own the data — pass from parent instead- Using `AnyView` type erasure — prefer `@ViewBuilder` or `Group` for conditional views- Ignoring `Sendable` requirements when passing data to/from actors ## References See skill: `swift-actor-persistence` for actor-based persistence patterns.See skill: `swift-protocol-di-testing` for protocol-based DI and testing with Swift Testing.