swift-ui-architect

安装量: 36
排名: #19259

安装

npx skills add https://github.com/pproenca/dot-skills --skill swift-ui-architect
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 + 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 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) @Observable for ViewModels/coordinators, ObservableObject / @Published never No dedicated use-case/interactor layer: ViewModels call Domain repository protocols directly Coordinator protocols live in Domain; concrete coordinators own NavigationPath in App target Route shells live in App target and own .navigationDestination mapping AppError + ErrorRouting drive 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 view diff-closure-skip - Use @SkipEquatable for closure/handler properties diff-reference-types - Never store reference types without Equatable conformance diff-identity-stability - Use stable O(1) identifiers in ForEach diff-avoid-anyview - Never use AnyView — use @ViewBuilder or generics diff-printchanges-debug - Use _printChanges() to diagnose unnecessary re-renders 2. State Architecture (CRITICAL) state-observable-class - Use @Observable classes for all ViewModels state-ownership - @State for owned data, plain property for injected data state-single-source - One source of truth per piece of state state-scoped-observation - Leverage @Observable property-level tracking state-binding-minimal - Pass @Binding only for two-way data flow state-environment-global - Use @Environment for app-wide shared dependencies state-no-published - Never use @Published or ObservableObject 3. View Composition (HIGH) view-body-complexity - Maximum 10 nodes in view body view-extract-subviews - Extract computed properties/helpers into separate View structs view-no-logic-in-body - Zero business logic in body view-minimal-dependencies - Pass only needed properties, not entire models view-viewbuilder-composition - Use @ViewBuilder for conditional composition view-no-init-sideeffects - Never perform work in View init 4. Navigation & Coordination (HIGH) nav-coordinator-pattern - Every feature has a coordinator owning NavigationStack nav-routes-enum - Define all routes as a Hashable enum nav-deeplink-support - Coordinators must support URL-based deep linking nav-modal-sheets - Present modals via coordinator, not inline nav-no-navigationlink - Never use NavigationLink(destination:) — use navigationDestination(for:) 5. Layer Architecture (HIGH) layer-dependency-rule - Domain layer has zero framework imports layer-usecase-protocol - Do not add a use-case layer; keep orchestration in ViewModel + repository protocols layer-repository-protocol - Repository protocols in Domain, implementations in Data layer-model-value-types - Domain models are structs, never classes layer-no-view-repository - Views never access repositories directly; ViewModel calls repository protocols layer-viewmodel-boundary - ViewModels expose display-ready state only 6. Dependency Injection (MEDIUM-HIGH) di-environment-injection - Inject container-managed protocol dependencies via @Environment di-protocol-abstraction - All injected dependencies are protocol types di-container-composition - Compose DependencyContainer in App target and expose VM factories di-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 element list-filter-in-model - Filter/sort in ViewModel, never inside ForEach list-lazy-stacks - Use LazyVStack/LazyHStack for unbounded content list-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 trigger data-async-init - Never perform async work in init data-error-loadable - Model loading states as enum, not booleans data-combine-avoid - Prefer async/await over Combine for new code data-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
返回排行榜