A reference implementation of a SwiftUI banking application using the MVVM-C-R (Model-View-ViewModel-Coordinator- Router) architecture pattern.
Universal deep linking — Navigate to any screen via URL scheme
bankapp://. Supports authentication-aware routing, tab switching, and nested navigation.
| Document | Description |
|---|---|
| Architecture Overview | MVVM-C pattern, folder structure, component responsibilities |
| Navigation Patterns | iOS 15 navigation, coordinators, deep linking |
| Dependency Injection | DI container, service layer, mock implementations |
| Adding Features | Step-by-step guide for implementing new features |
| Architecture Decisions | ADRs explaining key design choices |
| Code Conventions | Naming, patterns, logging, formatting |
| Component | Technology |
|---|---|
| Platform | iOS 15.0+ |
| UI Framework | SwiftUI |
| Architecture | MVVM-C-R (Coordinator + Router) |
| Reactive | Combine |
| Language | Swift 5.9 |
| Logging | OSLog |
| Secure Storage | Keychain |
| Biometrics | LocalAuthentication |
-
Authentication
- Login with username/password
- Biometric authentication (Face ID / Touch ID)
- OTP verification
- Session management
- Forgot/Reset password
-
Accounts
- Account list with balances
- Account detail view
- Transaction history with pagination
- Transaction detail
- Statement download
-
Transfers
- Internal transfers (between own accounts)
- External transfers (to beneficiaries)
- Transfer confirmation with OTP
- Transfer receipt
-
Beneficiary Management
- Beneficiary list
- Add new beneficiary
- Edit beneficiary
- Delete beneficiary
- Card management (list, detail, limits, block/unblock)
- Profile and settings
- Security settings
- Notification preferences
- Xcode 15.0+
- iOS 15.0+ Simulator or Device
- macOS Sonoma or later (recommended)
git clone <repository-url>
cd mykuik-al-architectural-proposal- Open project in Xcode
- Select iOS Simulator (iPhone 15 recommended)
- Build and Run (Cmd + R)
| Username | Password |
|---|---|
user |
password |
OTP code for testing: 123456
mykuik-al-architectural-proposal/
├── Sources/
│ ├── App/ # App entry point
│ ├── Router/ # Routes & deep linking (domain-split)
│ │ ├── Route.swift # Protocol, NavigationItem, DeepLinkError
│ │ ├── AppRoute.swift # Root route enum
│ │ ├── HomeRoute.swift # Home routes + parser
│ │ ├── AccountsRoute.swift # Accounts routes + parser
│ │ ├── TransferRoute.swift # Transfer routes + parser
│ │ ├── CardsRoute.swift # Cards routes + parser
│ │ ├── MoreRoute.swift # More routes + parser
│ │ ├── AuthRoute.swift # Auth routes + parser
│ │ └── DeepLinkParser.swift# Orchestrator
│ ├── Coordinator/ # Navigation coordinators
│ ├── ViewFactory/ # View+ViewModel factories
│ ├── DI/ # Dependency container
│ ├── Services/ # Service protocols & implementations
│ ├── Models/ # Domain models
│ ├── ViewModels/ # Business logic
│ ├── Views/ # SwiftUI views
│ └── Utilities/ # Logging, extensions
├── readme/ # Developer documentation
│ ├── 01-architecture-overview.md
│ ├── 02-navigation-patterns.md
│ ├── 03-dependency-injection.md
│ ├── 04-adding-features.md
│ ├── 05-decisions.md
│ └── 06-conventions.md
└── Package.swift
graph LR
View[View<br/>SwiftUI] <--> ViewModel[ViewModel<br/>Logic]
ViewModel <--> Service[Service<br/>Data]
View --> Coordinator[Coordinator<br/>Navigation]
ViewModel --> Coordinator
Uses NavigationView with hidden NavigationLink pattern for programmatic navigation (NavigationStack requires iOS 16+).
Constraints:
- NO NavigationStack (iOS 16+)
- NO navigationDestination modifier (iOS 16+)
- USE NavigationView with
.navigationViewStyle(.stack) - USE
NavigationLink(destination:isActive:)for programmatic navigation
Supports URL scheme bankapp:// for navigation to any screen:
bankapp://accounts/ACC123bankapp://transfer/beneficiariesbankapp://cards/CARD456/settings
| Purpose | File |
|---|---|
| App Entry | Sources/App/BankingApp.swift |
| Root Coordinator | Sources/Coordinator/AppCoordinator.swift |
| Route Protocol | Sources/Router/Route.swift |
| Deep Link Parser | Sources/Router/DeepLinkParser.swift |
| Feature Routes | Sources/Router/{Feature}Route.swift |
| DI Container | Sources/DI/DependencyContainer.swift |
| Example Coordinator | Sources/Coordinator/Features/AccountsCoordinator.swift |
| Example ViewModel | Sources/ViewModels/Accounts/AccountDetailViewModel.swift |
See Adding Features Guide for step-by-step instructions.
Quick checklist:
- Create
{Feature}Route.swiftwith route enum andparse()method - Add case to
AppRoute.swift - Register in
DeepLinkParser.swiftorchestrator - Create/update coordinator
- Create ViewFactory
- Create ViewModel(s)
- Create View(s)
- Use
Logger.{category}for logging (neverprint()) - Mask sensitive data (account numbers, card numbers)
- Always handle loading, error, and empty states
- Use
weakfor coordinator references in ViewModels
See Code Conventions for full details.
Key decisions documented in ADRs:
| ADR | Decision |
|---|---|
| 001 | MVVM-C-R over MVVM/TCA |
| 002 | NavigationView for iOS 15 compatibility |
| 003 | Weak coordinator references |
| 004 | Mock services for POC phase |
| 005 | Combine over external state management |
| 006 | Per-feature coordinators |
| 007 | Type-safe routing |
| 008 | Lazy service initialization |
| 009 | OSLog for logging |
