Apple SwiftUI iOS Design Best Practices
A builder's guide for implementing Apple-quality iOS interfaces in SwiftUI, grounded in two foundational design texts:
- Ken Kocienda — Creative Selection (empathy for the user, craft in coding, taste in choosing the best solution, demo culture of iterative refinement)
- John Edson — Design Like Apple (systems thinking, the product is the marketing, design out loud, design with conviction)
Contains 62 rules across 8 principle-based categories. Each rule identifies a specific anti-pattern, grounds the fix in a named principle, and provides the correct iOS 26 / Swift 6.2 SwiftUI implementation.
Scope & Relationship to Sibling Skills
This skill is the building and implementation guide — it teaches how to construct new SwiftUI interfaces from scratch using Apple-quality patterns. When loaded alongside ios-ui-refactor (reviewing/refactoring existing UI), this skill covers the greenfield implementation that ios-ui-refactor later audits. Use this skill for building new screens; use the sibling for evaluating and improving existing ones.
Clinic Architecture Contract (iOS 26 / Swift 6.2)
All guidance in this skill assumes the clinic modular MVVM-C architecture:
- Feature modules import
Domain + DesignSystem only (never Data, never sibling features)
- App target is the convergence point and owns
DependencyContainer, concrete coordinators, and Route Shell wiring
Domain stays pure Swift and defines models plus repository, *Coordinating, ErrorRouting, and AppError contracts
Data owns SwiftData/network/sync/retry/background I/O and implements Domain protocols
- Read/write flow defaults to stale-while-revalidate reads and optimistic queued writes
- ViewModels call repository protocols directly (no default use-case/interactor layer)
When to Apply
Reference these guidelines when:
- Building new SwiftUI views and screens from scratch
- Choosing between semantic colors, system typography, and spacing grids (Edson's Systems Thinking)
- Managing state with @State, @Binding, @Observable, @Environment (Kocienda's Craft)
- Selecting the right component: List vs LazyVStack, Sheet vs FullScreenCover (Kocienda's Taste)
- Composing views with @ViewBuilder, custom modifiers, and value types (Kocienda's Creative Selection)
- Implementing navigation with NavigationStack, TabView, sheets (Edson's Conversation)
- Laying out content with stacks, grids, frames, and adaptive layouts (Edson's Design Out Loud)
- Ensuring VoiceOver, touch targets, Dark Mode, and reduce motion support (Kocienda's Empathy)
- Adding transitions, loading states, and animation polish (Edson's Product Is the Marketing)
Rule Categories by Priority
| Priority |
Category |
Principle |
Impact |
Prefix |
Rules |
| 1 |
Empathy in Every Pixel |
Kocienda "Empathy" · Edson "Design Is About People" |
CRITICAL |
empathy- |
8 |
| 2 |
The Visual System |
Edson "Systems Thinking" · Kocienda "Convergence" |
CRITICAL |
system- |
8 |
| 3 |
Craft: State as Foundation |
Kocienda "Craft" |
CRITICAL |
craft- |
7 |
| 4 |
Creative Composition |
Kocienda "Creative Selection" |
HIGH |
compose- |
6 |
| 5 |
Taste: The Right Choice |
Kocienda "Taste" · Edson "Design with Conviction" |
HIGH |
taste- |
8 |
| 6 |
Navigation as Conversation |
Edson "Design Is a Conversation" · Kocienda "The Demo" |
HIGH |
converse- |
9 |
| 7 |
Design Out Loud: Layout |
Edson "Design Out Loud" · Kocienda "Intersection" |
HIGH |
layout- |
8 |
| 8 |
The Product Speaks |
Edson "Product Is the Marketing" · Kocienda "Demo Culture" |
MEDIUM |
product- |
8 |
Quick Reference
1. Empathy in Every Pixel (CRITICAL)
Kocienda: "Empathy — trying to see the world from other people's perspectives." Edson: design begins with the person holding the device.
empathy-semantic-colors - Use semantic colors, never hard-coded values
empathy-dark-mode - Support Dark Mode from day one
empathy-foreground-style - Use foregroundStyle over foregroundColor
empathy-safe-areas - Always respect safe areas for content
empathy-voiceover-labels - Add VoiceOver labels to every interactive element
empathy-touch-targets - Ensure 44x44 point minimum touch targets
empathy-reduce-motion - Always provide reduce motion fallback
empathy-readable-width - Constrain text to readable width on iPad
2. The Visual System (CRITICAL)
Edson: "Zoom out to see relationships between objects." Kocienda: convergence — many decisions narrowing toward one coherent whole.
system-typography - Use system typography styles, never fixed sizes
system-visual-hierarchy - Establish clear visual hierarchy through size, weight, and color
system-spacing-grid - Use a 4pt base unit for all spacing
system-material-backgrounds - Use material backgrounds for depth and layering
system-sf-symbols - Use SF Symbols for consistent iconography
system-gradients - Apply gradients for visual depth, not decoration
system-standard-margins - Use system standard margins consistently
system-stack-config - Configure stack alignment and spacing explicitly
3. Craft: State as Foundation (CRITICAL)
Kocienda: "Craft — applying skill to achieve a high-quality result."
craft-state-local - Use @State for view-local value types
craft-state-binding - Use @Binding for child view mutations
craft-state-environment - Use @Environment for shared app-wide data
craft-state-observable - Use @Observable for model classes
craft-avoid-body-state - Never create state inside the view body
craft-minimize-scope - Minimize state scope to reduce re-renders
craft-state-bindable - Use @Bindable for @Observable bindings
4. Creative Composition (HIGH)
Kocienda: "Creative selection — great software is built through composition and recombination."
compose-body-some-view - Return some View from body, never concrete types
compose-custom-properties - Use properties to make views configurable
compose-modifier-order - Apply view modifiers in the correct order
compose-viewbuilder - Use @ViewBuilder for flexible slot-based composition
compose-prefer-value-types - Prefer value types for view data
compose-prefer-composition - Prefer composition over inheritance for view reuse
5. Taste: The Right Choice (HIGH)
Kocienda: "Taste — refined judgment, the ability to choose the one right solution." Edson: commit to one approach and perfect it.
taste-list-vs-lazyvstack - Choose List for system features, LazyVStack for custom layouts
taste-sheet-vs-fullscreen - Choose sheet for tasks, fullScreenCover for immersion
taste-picker - Choose the right picker style for the data type
taste-grid-vs-lazygrid - Choose Grid for aligned data, LazyVGrid for scrollable collections
taste-button - Use button styles that match the action's importance
taste-textfield - Configure text input with the right keyboard and content type
taste-alerts - Use alerts only for critical, blocking information
taste-action-sheets - Use confirmation dialogs for contextual multi-choice actions
6. Navigation as Conversation (HIGH)
Edson: "Design is a conversation between the product and the person." Kocienda: demos as conversations about whether the interface speaks clearly.
converse-navigationstack - Use NavigationStack for programmatic, type-safe navigation
converse-tabview - Organize app sections with TabView for parallel navigation
converse-sheet-item - Use item binding for data-driven sheet presentation
converse-dismiss - Use environment dismiss for modal closure
converse-toolbar - Place toolbar items in the correct semantic positions
converse-tab-bar - Use tab bar for top-level section navigation
converse-nav-bar - Configure navigation bar to communicate context
converse-hierarchy - Design clear navigation hierarchy before writing code
converse-search - Integrate search with the searchable modifier
7. Design Out Loud: Layout (HIGH)
Edson: "Design Out Loud — prototype relentlessly until layout feels inevitable." Kocienda: the intersection of technology and liberal arts.
layout-stacks - Use stacks instead of manual positioning
layout-spacer - Use Spacer for flexible space distribution
layout-frame-sizing - Use frame() for explicit size constraints
layout-zstack - Use ZStack for purposeful layered composition
layout-grid - Use Grid for aligned non-scrolling tabular content
layout-lazy-grids - Use LazyVGrid for scrollable multi-column layouts
layout-adaptive - Use adaptive layouts for different size classes
layout-scroll-indicators - Show scroll indicators for long scrollable content
8. The Product Speaks (MEDIUM)
Edson: "The product itself is the marketing." Kocienda: every animation and loading state built to survive Steve Jobs' scrutiny.
product-transitions - Use semantic transitions for appearing views
product-loading-states - Show honest loading states, not indefinite spinners
product-with-animation - Use withAnimation for explicit state-driven animation
product-matched-geometry - Use matchedGeometryEffect for contextual origin transitions
product-list-cells - Design list cells with standard layouts
product-content-unavailable - Use ContentUnavailableView for empty and error states
product-segmented - Use segmented controls for visible, mutually exclusive options
product-menus - Use menus for secondary actions without cluttering the interface
How to Use
Read individual reference files for detailed explanations and code examples:
- Section definitions - Category structure, principle sources, and impact levels
- Rule template - Template for adding new rules
Reference Files
| File |
Description |
| references/_sections.md |
Category definitions and principle grounding |
| assets/templates/_template.md |
Template for new rules |
| metadata.json |
Version and reference information |
1---2name: ios-design3description: SwiftUI interface implementation patterns aligned with the iOS 26 / Swift 6.2 clinic modular MVVM-C architecture, grounded in Creative Selection and Design Like Apple principles. Use when building new SwiftUI views/screens while respecting Domain/Data boundaries, App-target route-shell navigation, and production-grade accessibility/interaction standards.4---5
6# Apple SwiftUI iOS Design Best Practices
7
8A builder's guide for implementing Apple-quality iOS interfaces in SwiftUI, grounded in two foundational design texts:
9
10- **Ken Kocienda** — *Creative Selection* (empathy for the user, craft in coding, taste in choosing the best solution, demo culture of iterative refinement)
11- **John Edson** — *Design Like Apple* (systems thinking, the product is the marketing, design out loud, design with conviction)
12
13Contains 62 rules across 8 principle-based categories. Each rule identifies a specific anti-pattern, grounds the fix in a named principle, and provides the correct iOS 26 / Swift 6.2 SwiftUI implementation.
14
15## Scope & Relationship to Sibling Skills
16
17This skill is the **building and implementation guide** — it teaches how to construct new SwiftUI interfaces from scratch using Apple-quality patterns. When loaded alongside `ios-ui-refactor` (reviewing/refactoring existing UI), this skill covers the greenfield implementation that `ios-ui-refactor` later audits. Use this skill for building new screens; use the sibling for evaluating and improving existing ones.
18
19
20## Clinic Architecture Contract (iOS 26 / Swift 6.2)
21
22All guidance in this skill assumes the clinic modular MVVM-C architecture:
23
24- Feature modules import `Domain` + `DesignSystem` only (never `Data`, never sibling features)
25- App target is the convergence point and owns `DependencyContainer`, concrete coordinators, and Route Shell wiring
26- `Domain` stays pure Swift and defines models plus repository, `*Coordinating`, `ErrorRouting`, and `AppError` contracts
27- `Data` owns SwiftData/network/sync/retry/background I/O and implements Domain protocols
28- Read/write flow defaults to stale-while-revalidate reads and optimistic queued writes
29- ViewModels call repository protocols directly (no default use-case/interactor layer)
30
31## When to Apply
32
33Reference these guidelines when:
34- Building new SwiftUI views and screens from scratch
35- Choosing between semantic colors, system typography, and spacing grids (Edson's Systems Thinking)
36- Managing state with @State, @Binding, @Observable, @Environment (Kocienda's Craft)
37- Selecting the right component: List vs LazyVStack, Sheet vs FullScreenCover (Kocienda's Taste)
38- Composing views with @ViewBuilder, custom modifiers, and value types (Kocienda's Creative Selection)
39- Implementing navigation with NavigationStack, TabView, sheets (Edson's Conversation)
40- Laying out content with stacks, grids, frames, and adaptive layouts (Edson's Design Out Loud)
41- Ensuring VoiceOver, touch targets, Dark Mode, and reduce motion support (Kocienda's Empathy)
42- Adding transitions, loading states, and animation polish (Edson's Product Is the Marketing)
43
44## Rule Categories by Priority
45
46| Priority | Category | Principle | Impact | Prefix | Rules |
47|----------|----------|-----------|--------|--------|-------|
48| 1 | Empathy in Every Pixel | Kocienda "Empathy" · Edson "Design Is About People" | CRITICAL | `empathy-` | 8 |
49| 2 | The Visual System | Edson "Systems Thinking" · Kocienda "Convergence" | CRITICAL | `system-` | 8 |
50| 3 | Craft: State as Foundation | Kocienda "Craft" | CRITICAL | `craft-` | 7 |
51| 4 | Creative Composition | Kocienda "Creative Selection" | HIGH | `compose-` | 6 |
52| 5 | Taste: The Right Choice | Kocienda "Taste" · Edson "Design with Conviction" | HIGH | `taste-` | 8 |
53| 6 | Navigation as Conversation | Edson "Design Is a Conversation" · Kocienda "The Demo" | HIGH | `converse-` | 9 |
54| 7 | Design Out Loud: Layout | Edson "Design Out Loud" · Kocienda "Intersection" | HIGH | `layout-` | 8 |
55| 8 | The Product Speaks | Edson "Product Is the Marketing" · Kocienda "Demo Culture" | MEDIUM | `product-` | 8 |
56
57## Quick Reference
58
59### 1. Empathy in Every Pixel (CRITICAL)
60
61Kocienda: "Empathy — trying to see the world from other people's perspectives." Edson: design begins with the person holding the device.
62
63- [`empathy-semantic-colors`](references/empathy-semantic-colors.md) - Use semantic colors, never hard-coded values
64- [`empathy-dark-mode`](references/empathy-dark-mode.md) - Support Dark Mode from day one
65- [`empathy-foreground-style`](references/empathy-foreground-style.md) - Use foregroundStyle over foregroundColor
66- [`empathy-safe-areas`](references/empathy-safe-areas.md) - Always respect safe areas for content
67- [`empathy-voiceover-labels`](references/empathy-voiceover-labels.md) - Add VoiceOver labels to every interactive element
68- [`empathy-touch-targets`](references/empathy-touch-targets.md) - Ensure 44x44 point minimum touch targets
69- [`empathy-reduce-motion`](references/empathy-reduce-motion.md) - Always provide reduce motion fallback
70- [`empathy-readable-width`](references/empathy-readable-width.md) - Constrain text to readable width on iPad
71
72### 2. The Visual System (CRITICAL)
73
74Edson: "Zoom out to see relationships between objects." Kocienda: convergence — many decisions narrowing toward one coherent whole.
75
76- [`system-typography`](references/system-typography.md) - Use system typography styles, never fixed sizes
77- [`system-visual-hierarchy`](references/system-visual-hierarchy.md) - Establish clear visual hierarchy through size, weight, and color
78- [`system-spacing-grid`](references/system-spacing-grid.md) - Use a 4pt base unit for all spacing
79- [`system-material-backgrounds`](references/system-material-backgrounds.md) - Use material backgrounds for depth and layering
80- [`system-sf-symbols`](references/system-sf-symbols.md) - Use SF Symbols for consistent iconography
81- [`system-gradients`](references/system-gradients.md) - Apply gradients for visual depth, not decoration
82- [`system-standard-margins`](references/system-standard-margins.md) - Use system standard margins consistently
83- [`system-stack-config`](references/system-stack-config.md) - Configure stack alignment and spacing explicitly
84
85### 3. Craft: State as Foundation (CRITICAL)
86
87Kocienda: "Craft — applying skill to achieve a high-quality result."
88
89- [`craft-state-local`](references/craft-state-local.md) - Use @State for view-local value types
90- [`craft-state-binding`](references/craft-state-binding.md) - Use @Binding for child view mutations
91- [`craft-state-environment`](references/craft-state-environment.md) - Use @Environment for shared app-wide data
92- [`craft-state-observable`](references/craft-state-observable.md) - Use @Observable for model classes
93- [`craft-avoid-body-state`](references/craft-avoid-body-state.md) - Never create state inside the view body
94- [`craft-minimize-scope`](references/craft-minimize-scope.md) - Minimize state scope to reduce re-renders
95- [`craft-state-bindable`](references/craft-state-bindable.md) - Use @Bindable for @Observable bindings
96
97### 4. Creative Composition (HIGH)
98
99Kocienda: "Creative selection — great software is built through composition and recombination."
100
101- [`compose-body-some-view`](references/compose-body-some-view.md) - Return some View from body, never concrete types
102- [`compose-custom-properties`](references/compose-custom-properties.md) - Use properties to make views configurable
103- [`compose-modifier-order`](references/compose-modifier-order.md) - Apply view modifiers in the correct order
104- [`compose-viewbuilder`](references/compose-viewbuilder.md) - Use @ViewBuilder for flexible slot-based composition
105- [`compose-prefer-value-types`](references/compose-prefer-value-types.md) - Prefer value types for view data
106- [`compose-prefer-composition`](references/compose-prefer-composition.md) - Prefer composition over inheritance for view reuse
107
108### 5. Taste: The Right Choice (HIGH)
109
110Kocienda: "Taste — refined judgment, the ability to choose the one right solution." Edson: commit to one approach and perfect it.
111
112- [`taste-list-vs-lazyvstack`](references/taste-list-vs-lazyvstack.md) - Choose List for system features, LazyVStack for custom layouts
113- [`taste-sheet-vs-fullscreen`](references/taste-sheet-vs-fullscreen.md) - Choose sheet for tasks, fullScreenCover for immersion
114- [`taste-picker`](references/taste-picker.md) - Choose the right picker style for the data type
115- [`taste-grid-vs-lazygrid`](references/taste-grid-vs-lazygrid.md) - Choose Grid for aligned data, LazyVGrid for scrollable collections
116- [`taste-button`](references/taste-button.md) - Use button styles that match the action's importance
117- [`taste-textfield`](references/taste-textfield.md) - Configure text input with the right keyboard and content type
118- [`taste-alerts`](references/taste-alerts.md) - Use alerts only for critical, blocking information
119- [`taste-action-sheets`](references/taste-action-sheets.md) - Use confirmation dialogs for contextual multi-choice actions
120
121### 6. Navigation as Conversation (HIGH)
122
123Edson: "Design is a conversation between the product and the person." Kocienda: demos as conversations about whether the interface speaks clearly.
124
125- [`converse-navigationstack`](references/converse-navigationstack.md) - Use NavigationStack for programmatic, type-safe navigation
126- [`converse-tabview`](references/converse-tabview.md) - Organize app sections with TabView for parallel navigation
127- [`converse-sheet-item`](references/converse-sheet-item.md) - Use item binding for data-driven sheet presentation
128- [`converse-dismiss`](references/converse-dismiss.md) - Use environment dismiss for modal closure
129- [`converse-toolbar`](references/converse-toolbar.md) - Place toolbar items in the correct semantic positions
130- [`converse-tab-bar`](references/converse-tab-bar.md) - Use tab bar for top-level section navigation
131- [`converse-nav-bar`](references/converse-nav-bar.md) - Configure navigation bar to communicate context
132- [`converse-hierarchy`](references/converse-hierarchy.md) - Design clear navigation hierarchy before writing code
133- [`converse-search`](references/converse-search.md) - Integrate search with the searchable modifier
134
135### 7. Design Out Loud: Layout (HIGH)
136
137Edson: "Design Out Loud — prototype relentlessly until layout feels inevitable." Kocienda: the intersection of technology and liberal arts.
138
139- [`layout-stacks`](references/layout-stacks.md) - Use stacks instead of manual positioning
140- [`layout-spacer`](references/layout-spacer.md) - Use Spacer for flexible space distribution
141- [`layout-frame-sizing`](references/layout-frame-sizing.md) - Use frame() for explicit size constraints
142- [`layout-zstack`](references/layout-zstack.md) - Use ZStack for purposeful layered composition
143- [`layout-grid`](references/layout-grid.md) - Use Grid for aligned non-scrolling tabular content
144- [`layout-lazy-grids`](references/layout-lazy-grids.md) - Use LazyVGrid for scrollable multi-column layouts
145- [`layout-adaptive`](references/layout-adaptive.md) - Use adaptive layouts for different size classes
146- [`layout-scroll-indicators`](references/layout-scroll-indicators.md) - Show scroll indicators for long scrollable content
147
148### 8. The Product Speaks (MEDIUM)
149
150Edson: "The product itself is the marketing." Kocienda: every animation and loading state built to survive Steve Jobs' scrutiny.
151
152- [`product-transitions`](references/product-transitions.md) - Use semantic transitions for appearing views
153- [`product-loading-states`](references/product-loading-states.md) - Show honest loading states, not indefinite spinners
154- [`product-with-animation`](references/product-with-animation.md) - Use withAnimation for explicit state-driven animation
155- [`product-matched-geometry`](references/product-matched-geometry.md) - Use matchedGeometryEffect for contextual origin transitions
156- [`product-list-cells`](references/product-list-cells.md) - Design list cells with standard layouts
157- [`product-content-unavailable`](references/product-content-unavailable.md) - Use ContentUnavailableView for empty and error states
158- [`product-segmented`](references/product-segmented.md) - Use segmented controls for visible, mutually exclusive options
159- [`product-menus`](references/product-menus.md) - Use menus for secondary actions without cluttering the interface
160
161## How to Use
162
163Read individual reference files for detailed explanations and code examples:
164
165- [Section definitions](references/_sections.md) - Category structure, principle sources, and impact levels
166- [Rule template](assets/templates/_template.md) - Template for adding new rules
167
168## Reference Files
169
170| File | Description |
171|------|-------------|
172| [references/_sections.md](references/_sections.md) | Category definitions and principle grounding |
173| [assets/templates/_template.md](assets/templates/_template.md) | Template for new rules |
174| [metadata.json](metadata.json) | Version and reference information |