swift-ui-architect
24
总安装量
24
周安装量
#15612
全站排名
安装命令
npx skills add https://github.com/pproenca/dot-skills --skill swift-ui-architect
Agent 安装分布
codex
21
gemini-cli
20
github-copilot
20
kimi-cli
19
opencode
19
amp
18
Skill 文档
SwiftUI Modular MVVM-C Architecture
Opinionated architecture enforcement for SwiftUI clinic-style apps. This skill aligns to the iOS 26 / Swift 6.2 clinic architecture: modular MVVM-C in local SPM packages, concrete coordinators and route shells in the App target, pure Domain protocols, and Data as the only I/O layer.
Mandated Architecture Stack
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â App target: DependencyContainer, Coordinators, Route Shells â
âââââââââââââââââ¬ââââââââââââââââ¬ââââââââââââââââ¬âââââââââââââââ¤
â Feature* SPM â Feature* SPM â Feature* SPM â Feature* SPM â
â View + VM â View + VM â View + VM â View + VM â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â Data SPM: repository impls, remote/local, retry, sync queue â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â Domain SPM: models, repository protocols, coordinator protocolsâ
â and ErrorRouting/AppError â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â Shared SPMs: DesignSystem, SharedKit â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Dependency Rule: Feature modules import Domain + DesignSystem only. Features never import Data or other features. App target is the only convergence point.
Clinic Architecture Contract (iOS 26 / Swift 6.2)
All guidance in this skill assumes the clinic modular MVVM-C architecture:
- Feature modules import
Domain+DesignSystemonly (neverData, never sibling features) - App target is the convergence point and owns
DependencyContainer, concrete coordinators, and Route Shell wiring Domainstays pure Swift and defines models plus repository,*Coordinating,ErrorRouting, andAppErrorcontractsDataowns 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 or refactoring feature modules under local SPM packages
- Wiring coordinators, route shells, and dependency container factories
- Defining Domain protocols for repositories, coordinators, and error routing
- Enforcing Data-only ownership of networking, persistence, and sync
- Reviewing stale-while-revalidate reads and optimistic queued writes
Non-Negotiable Constraints (iOS 26 / Swift 6.2)
@Observablefor ViewModels/coordinators,ObservableObject/@Publishednever- No dedicated use-case/interactor layer: ViewModels call Domain repository protocols directly
- Coordinator protocols live in Domain; concrete coordinators own
NavigationPathin App target - Route shells live in App target and own
.navigationDestinationmapping AppError+ErrorRoutingdrive presentation policy; ViewModels do not hardcode global error UI- SwiftData / URLSession / retry / sync queue logic stays in Data package only
Rule Categories by Priority
| Priority | Category | Impact | Prefix | Rules |
|---|---|---|---|---|
| 1 | View Identity & Diffing | CRITICAL | diff- |
6 |
| 2 | State Architecture | CRITICAL | state- |
7 |
| 3 | View Composition | HIGH | view- |
6 |
| 4 | Navigation & Coordination | HIGH | nav- |
5 |
| 5 | Layer Architecture | HIGH | layer- |
6 |
| 6 | Dependency Injection | MEDIUM-HIGH | di- |
4 |
| 7 | List & Collection Performance | MEDIUM | list- |
4 |
| 8 | Async & Data Flow | MEDIUM | data- |
5 |
Quick Reference
1. View Identity & Diffing (CRITICAL)
diff-equatable-views– Apply @Equatable macro to every SwiftUI viewdiff-closure-skip– Use @SkipEquatable for closure/handler propertiesdiff-reference-types– Never store reference types without Equatable conformancediff-identity-stability– Use stable O(1) identifiers in ForEachdiff-avoid-anyview– Never use AnyView â use @ViewBuilder or genericsdiff-printchanges-debug– Use _printChanges() to diagnose unnecessary re-renders
2. State Architecture (CRITICAL)
state-observable-class– Use @Observable classes for all ViewModelsstate-ownership– @State for owned data, plain property for injected datastate-single-source– One source of truth per piece of statestate-scoped-observation– Leverage @Observable property-level trackingstate-binding-minimal– Pass @Binding only for two-way data flowstate-environment-global– Use @Environment for app-wide shared dependenciesstate-no-published– Never use @Published or ObservableObject
3. View Composition (HIGH)
view-body-complexity– Maximum 10 nodes in view bodyview-extract-subviews– Extract computed properties/helpers into separate View structsview-no-logic-in-body– Zero business logic in bodyview-minimal-dependencies– Pass only needed properties, not entire modelsview-viewbuilder-composition– Use @ViewBuilder for conditional compositionview-no-init-sideeffects– Never perform work in View init
4. Navigation & Coordination (HIGH)
nav-coordinator-pattern– Every feature has a coordinator owning NavigationStacknav-routes-enum– Define all routes as a Hashable enumnav-deeplink-support– Coordinators must support URL-based deep linkingnav-modal-sheets– Present modals via coordinator, not inlinenav-no-navigationlink– Never use NavigationLink(destination:) â use navigationDestination(for:)
5. Layer Architecture (HIGH)
layer-dependency-rule– Domain layer has zero framework importslayer-usecase-protocol– Do not add a use-case layer; keep orchestration in ViewModel + repository protocolslayer-repository-protocol– Repository protocols in Domain, implementations in Datalayer-model-value-types– Domain models are structs, never classeslayer-no-view-repository– Views never access repositories directly; ViewModel calls repository protocolslayer-viewmodel-boundary– ViewModels expose display-ready state only
6. Dependency Injection (MEDIUM-HIGH)
di-environment-injection– Inject container-managed protocol dependencies via @Environmentdi-protocol-abstraction– All injected dependencies are protocol typesdi-container-composition– ComposeDependencyContainerin App target and expose VM factoriesdi-mock-testing– Every protocol dependency has a mock for testing
7. List & Collection Performance (MEDIUM)
list-constant-viewcount– ForEach must produce constant view count per elementlist-filter-in-model– Filter/sort in ViewModel, never inside ForEachlist-lazy-stacks– Use LazyVStack/LazyHStack for unbounded contentlist-id-keypath– Provide explicit id keyPath â never rely on implicit identity
8. Async & Data Flow (MEDIUM)
data-task-modifier– Use.task(id:)as the primary feature data-loading triggerdata-async-init– Never perform async work in initdata-error-loadable– Model loading states as enum, not booleansdata-combine-avoid– Prefer async/await over Combine for new codedata-cancellation– Use .task automatic cancellation â never manage Tasks manually
How to Use
Read individual reference files for detailed explanations and code examples:
- Section definitions – Category structure and impact levels
- Rule template – Template for adding new rules
Reference Files
| File | Description |
|---|---|
| references/_sections.md | Category definitions and ordering |
| assets/templates/_template.md | Template for new rules |
| metadata.json | Version and reference information |