Refactors Swift/SwiftUI code into a modular MVVM-C architecture with @Observable ViewModels, coordinator pattern, and Domain/Data/Feature/App package boundaries. Use when migrating to iOS 26 / Swift 6.2 clinic architecture.
How this skill is triggered — by the user, by Claude, or both
Slash command
/pproenca-dot-skills-1:swift-refactorThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Comprehensive refactoring guide for migrating Swift/SwiftUI code to modular MVVM-C with local SPM package boundaries and App-target composition root wiring.
Comprehensive refactoring guide for migrating Swift/SwiftUI code to modular MVVM-C with local SPM package boundaries and App-target composition root wiring.
┌───────────────────────────────────────────────────────────────┐
│ App target: DependencyContainer, Coordinators, Route Shells │
├───────────────────────────────────────────────────────────────┤
│ Feature modules: View + ViewModel (Domain + DesignSystem deps)│
├───────────────────────────────────────────────────────────────┤
│ Data package: repositories, remote/local stores, sync, retry │
├───────────────────────────────────────────────────────────────┤
│ Domain package: models, repository/coordinator/error protocols │
└───────────────────────────────────────────────────────────────┘
Dependency Rule: Feature modules never import Data and never import sibling features.
All guidance in this skill assumes the clinic modular MVVM-C architecture:
Domain + DesignSystem only (never Data, never sibling features)DependencyContainer, concrete coordinators, and Route Shell wiringDomain stays pure Swift and defines models plus repository, *Coordinating, ErrorRouting, and AppError contractsData owns SwiftData/network/sync/retry/background I/O and implements Domain protocolsReference these guidelines when:
DependencyContainer.task(id:) and cancellable loading@Observable ViewModels/coordinators, ObservableObject / @Published neverNavigationStack is owned by App-target route shells and coordinators@Equatable macro on every view, AnyView never| Priority | Category | Impact | Prefix | Rules |
|---|---|---|---|---|
| 1 | View Identity & Diffing | CRITICAL | diff- | 4 |
| 2 | API Modernization | CRITICAL | api- | 7 |
| 3 | State Architecture | CRITICAL | state- | 6 |
| 4 | View Composition | HIGH | view- | 7 |
| 5 | Navigation & Coordination | HIGH | nav- | 5 |
| 6 | Layer Architecture | HIGH | layer- | 5 |
| 7 | Architecture Patterns | HIGH | arch- | 5 |
| 8 | Dependency Injection | MEDIUM-HIGH | di- | 2 |
| 9 | Type Safety & Protocols | MEDIUM-HIGH | type- | 4 |
| 10 | List & Collection Performance | MEDIUM | list- | 4 |
| 11 | Async & Data Flow | MEDIUM | data- | 3 |
| 12 | Swift Language Fundamentals | MEDIUM | swift- | 8 |
diff-equatable-views - Add @Equatable macro to every SwiftUI viewdiff-closure-skip - Use @EquatableIgnored for closure propertiesdiff-identity-stability - Use stable O(1) identifiers in ForEachdiff-printchanges-debug - Use _printChanges() to diagnose re-rendersapi-observable-macro - Migrate ObservableObject to @Observable macroapi-navigationstack-migration - Replace NavigationView with NavigationStackapi-onchange-signature - Migrate to new onChange signatureapi-environment-object-removal - Replace @EnvironmentObject with @Environmentapi-alert-confirmation-dialog - Migrate Alert to confirmationDialog APIapi-list-foreach-identifiable - Replace id: .self with Identifiable conformanceapi-toolbar-migration - Replace navigationBarItems with toolbar modifierstate-scope-minimization - Minimize state scope to nearest consumerstate-derived-over-stored - Use computed properties over redundant @Statestate-binding-extraction - Extract @Binding to isolate child re-rendersstate-remove-observation - Migrate @ObservedObject to @Observable trackingstate-onappear-to-task - Replace onAppear closures with .task modifierstate-stateobject-placement - Migrate @StateObject to @State with @Observableview-extract-subviews - Extract subviews for diffing checkpointsview-eliminate-anyview - Replace AnyView with @ViewBuilder or genericsview-computed-to-struct - Convert computed view properties to struct viewsview-modifier-extraction - Extract repeated modifiers into custom ViewModifiersview-conditional-content - Use Group or conditional modifiers over conditional viewsview-preference-keys - Replace callback closures with PreferenceKeyview-body-complexity - Reduce view body to maximum 10 nodesnav-centralize-destinations - Refactor navigation to coordinator patternnav-value-based-links - Replace NavigationLink with coordinator routesnav-path-state-management - Use NavigationPath for programmatic navigationnav-split-view-adoption - Use NavigationSplitView for multi-column layoutsnav-sheet-item-pattern - Replace boolean sheet triggers with item bindinglayer-dependency-rule - Extract domain layer with zero framework importslayer-usecase-protocol - Remove use-case/interactor layer; keep orchestration in ViewModel + repository protocolslayer-repository-protocol - Repository protocols in Domain, implementations in Datalayer-no-view-repository - Remove direct repository access from viewslayer-viewmodel-boundary - Refactor ViewModels to expose display-ready state onlyarch-viewmodel-elimination - Restructure inline state into @Observable ViewModelarch-protocol-dependencies - Extract protocol dependencies through ViewModel layerarch-environment-key-injection - Use Environment keys for service injectionarch-feature-module-extraction - Extract features into independent modulesarch-model-view-separation - Extract business logic into Domain models and repository-backed ViewModelsdi-container-composition - Compose dependency container at app rootdi-mock-testing - Add mock implementation for every protocol dependencytype-tagged-identifiers - Replace String IDs with tagged typestype-result-over-optionals - Use Result type over optional with error flagtype-phantom-types - Use phantom types for compile-time state machinestype-force-unwrap-elimination - Eliminate force unwraps with safe alternativeslist-constant-viewcount - Ensure ForEach produces constant view count per elementlist-filter-in-model - Move filter/sort logic from ForEach into ViewModellist-lazy-stacks - Replace VStack/HStack with Lazy variants for unbounded contentlist-id-keypath - Provide explicit id keyPath — never rely on implicit identitydata-task-modifier - Replace onAppear async work with .task modifierdata-error-loadable - Model loading states as enum instead of boolean flagsdata-cancellation - Use .task automatic cancellation — never manage Tasks manuallyswift-let-vs-var - Use let for constants, var for variablesswift-structs-vs-classes - Prefer structs over classesswift-camel-case-naming - Use camelCase naming conventionswift-string-interpolation - Use string interpolation for dynamic textswift-functions-clear-names - Name functions and parameters for clarityswift-for-in-loops - Use for-in loops for collectionsswift-optionals - Handle optionals safely with unwrappingswift-closures - Use closures for inline functionsRead individual reference files for detailed explanations and code examples:
| File | Description |
|---|---|
| references/_sections.md | Category definitions and ordering |
| assets/templates/_template.md | Template for new rules |
npx claudepluginhub joshuarweaver/cascade-code-general-misc-1 --plugin pproenca-dot-skills-1Enforces opinionated SwiftUI modular MVVM-C architecture for iOS apps. Guides DependencyContainer, coordinators, route shells, and repository protocol enforcement.
Provides architecture playbooks for Swift iOS codebases (MVVM, MVI, TCA, Clean Architecture, VIPER, MVP, Coordinator, Reactive). Guides architecture selection, implementation, refactoring, and review for SwiftUI or UIKit features.
Refactors SwiftUI views for consistent structure, dependency injection, and Observation usage. Helps clean up view layout, handle view models safely, and standardize state initialization.