iOS SwiftUI Architect
Use for iOS SwiftUI UI structure and component choices. Read the nearest local example before introducing a new pattern.
Start
- Existing project: identify screen model (list/detail/editor/settings/tab), search for nearby examples (
rg "TabView\\(", etc.), then readreferences/components-index.md. - New app: start with
references/app-wiring.mdfor TabView + NavigationStack + sheets, then expand route/sheet enums as screens appear. - For scroll-driven reveals, read
references/scroll-reveal.mdbefore hand-rolling gestures.
Rules
- Prefer
@State,@Binding,@Observable, and@Environment; avoid unnecessary view models. - If iOS 16 or earlier is supported, use
ObservableObjectwith@StateObjectat the owner and@ObservedObjectfor injection. - Keep views small, composed, and project-formatted.
- Use
.task/.task(id:)with loading/error states; readreferences/async-state.mdfor cancellation/debouncing. - Put shared app services in
@Environment; keep feature-local dependencies as explicit inputs. - Prefer newest SwiftUI APIs that match deployment target and call out minimum OS.
- Maintain legacy patterns only inside legacy files.
- Sheets: prefer
.sheet(item:), avoidif letinside sheet bodies, let sheets calldismiss()internally. - Scroll reveals: derive one normalized progress value from scroll offset instead of parallel gesture state machines when possible.
State Ownership
| Scenario | Pattern |
|---|---|
| Local UI state | @State |
| Child mutates parent value | @Binding |
| Root-owned iOS 17+ reference model | @State with @Observable |
| Injected iOS 17+ observable | explicit stored property |
| Shared service/config | @Environment(Type.self) |
| iOS 16 legacy model | @StateObject owner, @ObservedObject injected |
Choose ownership first; do not introduce a reference model when value state is enough.
New View Workflow
- Define state ownership, dependencies, and minimum OS.
- Sketch hierarchy, routing, and presentation; read navigation/sheet/deeplink refs when complex.
- Build and verify before widening call-site changes.
- Add async loading and explicit error/loading UI when needed.
- Add previews for primary/secondary states and accessibility IDs/labels for interactive UI.
- Validate build/previews/state propagation/list identity/observation scope. If build fails, fix the exact error before continuing.
Anti-Patterns
- Giant views mixing layout, business logic, networking, routing, and formatting.
- Multiple booleans for exclusive sheets/alerts/destinations.
- Live service calls from
body. AnyViewas a composition escape hatch.- Defaulting every shared dependency to
@EnvironmentObjector a global router.
References
references/components-index.mdreferences/navigationstack.mdreferences/sheets.mdreferences/deeplinks.mdreferences/app-wiring.mdreferences/async-state.mdreferences/previews.mdreferences/performance.md
Use current Apple docs when API availability or platform guidance may have changed.