# swiftui-patterns

> A Claude Code skill from Affaan M's everything-claude-code repo for modern SwiftUI architecture — @Observable state management with property-level tracking, property-wrapper selection table (@State / @Binding / @Bindable / @Environment), type-safe NavigationStack flows, environment injection via @Environment(Type.self), and rendering-performance patterns for lists and complex layouts.

**Use case**: Pick the right SwiftUI property wrapper and view-composition pattern instead of defaulting to ObservableObject everywhere

**Canonical URL**: https://agentcookbooks.com/skills/swiftui-patterns/

**Topics**: claude-code, skills, ios, design

**Trigger phrases**: "should I use @State or @Observable here", "SwiftUI NavigationStack with type-safe routes", "fix re-render performance on this list"

**Source**: [Affaan M](https://github.com/affaan-m/everything-claude-code/tree/main/skills/swiftui-patterns)

**License**: MIT

---

## What it does

`swiftui-patterns` is the SwiftUI architecture skill in [Affaan M's everything-claude-code](https://github.com/affaan-m/everything-claude-code) — see [skills/swiftui-patterns](https://github.com/affaan-m/everything-claude-code/tree/main/skills/swiftui-patterns). It's the composition / state / navigation reference for declarative iOS / macOS UI — distinct from `liquid-glass-design` (which is about the iOS 26 material) and `swift-concurrency-6-2` (which is about actor isolation).

The property-wrapper selection table is the operational core: `@State` for view-local value types (toggles, form fields, sheet presentation), `@Binding` for two-way reference to parent's `@State`, `@Observable` class + `@State` for owned models with multiple properties, plain `@Observable` reference for read-only injection, `@Bindable` for two-way bindings into `@Observable` properties, `@Environment` for shared dependencies injected via `.environment()`. The shift from `ObservableObject` to `@Observable` is the modern default — `@Observable` tracks property-level changes so SwiftUI only re-renders views that actually read the changed property.

The skill covers `NavigationStack` patterns for type-safe navigation, view-composition rules (extract subviews to limit invalidation scope), `@Environment(Type.self)` as the modern replacement for `@EnvironmentObject`, and performance patterns for lists and complex layouts. View-model integration is shown explicitly: `@State private var viewModel: ItemListViewModel` with an `init` that initializes via `_viewModel = State(initialValue: viewModel)` — the modern shape rather than `@StateObject`.

## When to use it

- Building SwiftUI views and choosing the right state-management primitive (`@State` vs `@Observable` vs `@Binding`)
- Designing navigation flows with `NavigationStack` and type-safe destinations
- Structuring view models and data flow with `@Observable`
- Optimizing rendering performance for lists and complex layouts (extracting subviews to limit invalidation)
- Dependency injection via `@Environment(Type.self)` rather than `@EnvironmentObject`

When *not* to reach for it:

- Liquid Glass material application — that's `liquid-glass-design`
- Actor / concurrency / data-race work — that's `swift-concurrency-6-2`
- On-device LLM features — that's `foundation-models-on-device`
- UIKit-only code — the skill is SwiftUI-shaped

## Install

From [affaan-m/everything-claude-code](https://github.com/affaan-m/everything-claude-code) at `skills/swiftui-patterns/`. Drop the folder into `~/.claude/skills/swiftui-patterns/`. The skill is markdown + Swift code templates; the runtime is Xcode 26+ targeting iOS 17+ for the `@Observable` macro (older deployment targets are stuck with `ObservableObject`).

## What a session looks like

1. **Name the state.** "I have a list view that shows items, has a search field, and loads from a repository — what wrappers?"
2. **Skill walks the table.** `searchText` is view-local string editing → `@Binding` into the view model's `var searchText` via `$viewModel.searchText`. `items` and `isLoading` are owned by the view model → `@Observable` class with `private(set)` for the read-only fields.
3. **Wire the view model.** `@State private var viewModel: ItemListViewModel` with the `init` that uses `_viewModel = State(initialValue:)` to support custom initialization.
4. **`@Observable` for the model class.** No `@Published`. SwiftUI tracks property reads via the `@Observable` macro and re-renders only the views that read the changed property.
5. **`.task` for async load.** `await viewModel.load()` runs once when the view appears.
6. **Navigation.** `NavigationStack` with `navigationDestination(for:)` for type-safe routes — push a `Item.ID` onto the stack, the destination view receives it.
7. **Environment injection.** `.environment(authManager)` from the root, `@Environment(AuthManager.self)` in the consumer.

The discipline that makes it work: pick the simplest wrapper that fits. The selection table runs in increasing complexity — `@State` first, only escalate to `@Observable` when there are multiple related properties, only inject via `@Environment` when the dependency is genuinely shared.

## Receipts

_TODO — to be filled in from a real session. Once the patterns have been used to build a real SwiftUI screen, this section will capture: how often `@Observable` + property-level tracking actually narrowed the re-render scope vs. the operator's prior `ObservableObject` baseline, which property wrapper choice was wrong on first pass and needed swapping (the most common is reaching for `@Environment` when `@Bindable` would do), whether the `NavigationStack` type-safe routes held up against deep-link / restoration requirements, and the actual frame-time on a complex list before vs. after extracting subviews to limit invalidation._

## Source and attribution

From [Affaan M's everything-claude-code](https://github.com/affaan-m/everything-claude-code/tree/main/skills/swiftui-patterns) — an MIT-licensed skill collection covering harness construction, agent ops, video, payments, and platform-specific patterns.

License: MIT.