swiftui-expert
Installation
SKILL.md
SwiftUI Expert Skill
Agent Behavior Contract
When this skill is active, follow these rules strictly:
- Focus on facts and best practices, not architecture — defer architectural decisions (MVVM, MVC, VIPER, Clean Architecture, Coordinator) to
ios-architecture-expert. - Always prefer
@ObservableoverObservableObjectfor new code. Mark@Observableclasses with@MainActorunless using default actor isolation. - Never use
applyIfor generic conditional modifier helpers — they break view identity. - Prefer modifiers over conditional views for state changes (preserves structural identity).
- Use modern APIs over deprecated equivalents — see
references/modern-apis.md. - Lead with corrected/improved code when reviewing; explain why a pattern is better (diffing, thread safety, API correctness).
- Use "prefer"/"avoid" for recommendations; "always"/"never" only for API correctness.
- Respond in the same language the user writes in — default to English when uncertain.
- Adopt Liquid Glass only when explicitly requested — glass is for controls and navigation only (HIG).
- Gate iOS 26+ features with
#availableand provide fallbacks.
Diagnostic Table
| Symptom | First check | Smallest fix | Deep dive |
|---|---|---|---|
| Wrong property wrapper chosen | Ownership direction | Match wrapper to data flow | references/state-management.md |
| View re-renders too often | Dependency graph | Narrow state dependencies | references/performance-patterns.md |
| Deprecated API warning | API replacement table | Swap to modern equivalent | references/modern-apis.md |
| View body is 200+ lines | View extraction rules | Extract struct subviews | references/view-composition.md |
| ForEach flickers or reorders | Identity stability | Use stable Identifiable ID | references/list-patterns.md |
| Animation is janky or missing | Implicit vs explicit | Match animation to state change site | references/animation-basics.md |
| Glass effect on wrong layer | HIG compliance | Glass on controls only, not content | references/liquid-glass.md |
| Custom control lacks accessibility | Semantic components | Use Button/Label or accessibilityRepresentation |
references/accessibility-patterns.md |
Quick Summary
| Area | Key Principle | Reference |
|---|---|---|
| State Management | @Observable + @MainActor; @State for owned, @Binding for child-modifies-parent |
references/state-management.md |
| View Composition | Small single-responsibility views; extract structs, not @ViewBuilder functions |
references/view-composition.md |
| Modern APIs | foregroundStyle, clipShape, NavigationStack, Tab, Button over onTapGesture |
references/modern-apis.md |
| Performance | Cheap inits, pure body, narrow dependencies, stable ForEach identity | references/performance-patterns.md |
| Animations | withAnimation for events, .animation(_:value:) for reactive, transforms over layout |
references/animation-basics.md |
| Accessibility | Semantic fonts/styles, @ScaledMetric, accessibilityRepresentation for custom controls |
references/accessibility-patterns.md |
| Liquid Glass | Controls/navigation only (HIG); Glass.regular default; GlassEffectContainer for groups |
references/liquid-glass.md |
Quick Reference
Property Wrapper Selection
| Wrapper | Use When |
|---|---|
@State |
Internal view state (must be private), or owned @Observable class |
@Binding |
Child modifies parent's state |
@Bindable |
Injected @Observable needing bindings |
let |
Read-only value from parent |
var |
Read-only value watched via .onChange() |
Full guide including legacy wrappers: state-management.md
Modern API Replacements
| Deprecated | Modern Alternative |
|---|---|
foregroundColor() |
foregroundStyle() |
cornerRadius() |
clipShape(.rect(cornerRadius:)) |
tabItem() |
Tab API (iOS 18+) |
onTapGesture() |
Button (unless need location/count) |
NavigationView |
NavigationStack |
onChange(of:) { value in } |
onChange(of:) { old, new in } or onChange(of:) { } |
GeometryReader |
containerRelativeFrame() or visualEffect() |
Full table: modern-apis.md
Workflow Decision Tree
1) Review existing SwiftUI code
- Check property wrapper usage ->
references/state-management.md - Verify modern API usage ->
references/modern-apis.md - Verify view composition and extraction ->
references/view-composition.md - Check performance patterns ->
references/performance-patterns.md - Inspect accessibility and Liquid Glass ->
references/accessibility-patterns.md,references/liquid-glass.md
2) Improve existing SwiftUI code
- Audit state management (prefer
@ObservableoverObservableObject) ->references/state-management.md - Replace deprecated APIs ->
references/modern-apis.md - Extract complex views into subviews ->
references/view-composition.md - Optimize hot paths and list identity ->
references/performance-patterns.md,references/list-patterns.md - Improve animations and accessibility ->
references/animation-basics.md,references/accessibility-patterns.md
3) Implement new SwiftUI feature
- Design data flow first: owned vs injected state ->
references/state-management.md - Use modern APIs and
@Observable->references/modern-apis.md - Structure views for optimal diffing ->
references/view-composition.md - Apply correct animation patterns ->
references/animation-basics.md,references/animation-advanced.md - Add accessibility and glass effects (if requested) ->
references/accessibility-patterns.md,references/liquid-glass.md
Guardrails
- Do not enforce specific architectures (MVVM, MVC, VIPER) — defer to
ios-architecture-expert - Do not use
applyIfor conditional modifier helpers that break view identity - Do not declare passed values as
@Stateor@StateObject— they only accept initial values - Do not create objects or start Tasks in view initializers or
body - Do not use
.indicesfor ForEach identity with dynamic content - Do not apply glass effects to content layer views — glass is for controls and navigation only (HIG)
- Do not use
AnyViewin list rows - Do not use
GeometryReaderwhencontainerRelativeFrame(),onGeometryChange, orvisualEffectsuffice
Verification Checklist
When implementing or reviewing SwiftUI code:
- Property wrappers match ownership direction (
@Stateprivate,@Bindingfor modification,@Observablefor shared) - No deprecated APIs (
foregroundColor,cornerRadius,NavigationView,tabItem) - View body is pure — no side effects, no Task creation, no object allocation
- Complex views extracted into struct subviews (not
@ViewBuilderfunctions) - ForEach uses stable
Identifiableidentity (never.indices) - Animations use value parameter or
withAnimation(no deprecated parameterless.animation()) - Accessibility: semantic fonts,
@ScaledMetric,ButtonoveronTapGesture - Liquid Glass (if present):
#availablegated, controls-only,GlassEffectContainerfor groups - No
applyIf, no conditional modifier helpers, no if/else for style changes - Views work in any context (no hardcoded sizes, no
UIScreen.main.bounds)
Reference Router
Open the smallest reference that matches the question:
- State & Data Flow
- state-management.md — property wrappers, data flow, when to use a ViewModel
- View Structure
- view-composition.md — view extraction, styles, specialized views, reusability
- list-patterns.md — ForEach identity, stability, list best practices
- Modern APIs & Navigation
- modern-apis.md — modern API usage and deprecated replacements
- navigation-patterns.md — NavigationStack, deep linking, programmatic navigation
- scroll-patterns.md — ScrollView patterns and programmatic scrolling
- text-formatting.md — modern text formatting and string operations
- Performance & Optimization
- performance-patterns.md — optimization techniques and anti-patterns
- image-optimization.md — AsyncImage, image downsampling
- Animation
- animation-basics.md — core concepts, implicit/explicit animations
- animation-transitions.md — transitions, custom transitions, Animatable
- animation-advanced.md — transactions, phase/keyframe, completion handlers
- Accessibility & Platform
- accessibility-patterns.md — semantic styling, adaptive spacing, VoiceOver
- liquid-glass.md — iOS 26+ Liquid Glass API and HIG guidance
- Navigation index