SimpleShoppingList is an open-source SwiftUI sample project designed as a handoff-ready scaffold for junior and intermediate iOS developers.
The intent is to provide a practical, maintainable baseline that demonstrates MVVM structure, scene-owned navigation, protocol-based dependencies, and actor-backed persistence.
It is intentionally structured so developers can use it as a starting point for real product work.
- Provide a clean SwiftUI architecture baseline.
- Keep responsibilities separated (UI, navigation, state, persistence).
- Support multiple shopping lists and item-level editing workflows.
- Demonstrate protocol-first dependency design.
- Provide a learning-focused codebase that can evolve toward production.
- Swift 6
- SwiftUI
- Actor-based persistence store
- Async/await + AsyncStream for state updates
- JSON persistence in Documents directory
SimpleShoppingList/
Components/ # Reusable UI components
Models/ # Domain models + sample data
Protocols/ # Protocol contracts
Routes/ # Route enums for scene navigation
Scenes/ # Navigation roots (own NavigationStack + destinations)
Services/ # Concrete service/store implementations
ViewModels/ # Presentation/business logic
Views/ # Screen UI
Scene types are navigation owners:
DashboardSceneShoppingListsScene
Each scene owns:
- A
NavigationStack .navigationDestination(for:)handlers for its route type
This keeps navigation predictable and centralized.
Views focus on rendering and user interaction wiring.
ViewModels focus on:
- Business logic
- Async workflows
- Derived screen state
This keeps UI code smaller and easier to maintain.
ShoppingStore is an actor-backed store that persists to JSON in the app Documents directory.
It provides:
- List and item CRUD operations
listsStream()viaAsyncStreamfor updates- On-launch load from persisted JSON
Why this matters:
- Actor isolation improves concurrency safety.
AsyncStreamgives ordered asynchronous updates.- Data survives app restarts.
Dependencies are referenced through protocols:
ServiceContainerProtocolShoppingStoreProtocol
Concrete implementations are injected at app composition.
This enables easier mocking and testing of view models/services.
- Dashboard with totals and latest shopping list summary
- Multiple shopping lists
- Add/edit/delete shopping lists
- Add/edit/delete shopping list items
- Mark items as collected/purchased
- Item price support (numeric)
- Bootstrap seed data via
ServiceContainerProtocolwhen store is empty
- User action in
View/Component. - View forwards to
ViewModel. - ViewModel calls store protocol methods.
- Store mutates actor state and persists JSON.
- Store emits latest snapshot through
AsyncStream. - ViewModels update published state and SwiftUI re-renders.
The app writes shopping lists to a JSON file in the app Documents directory.
- Store:
Services/ShoppingStore.swift - Protocol:
Protocols/ShoppingStoreProtocol.swift
On launch, SimpleShoppingListApp triggers store bootstrapping through ServiceContainerProtocol to seed mock data only when the store is empty.
From project root:
xcodebuild -project SimpleShoppingList.xcodeproj -scheme SimpleShoppingList -destination 'platform=iOS Simulator,name=iPhone 17 Pro' buildOr open SimpleShoppingList.xcodeproj in Xcode and run the SimpleShoppingList scheme.
- Add focused unit tests for view models and store logic.
- Add CI build/lint/test pipeline.
- Add localization + accessibility audit.
- Add data migration strategy for future model changes.
- Add import/export backup flow.
This repository is useful for:
- Junior/intermediate Swift developers learning scalable app structure.
- Teams needing a clean SwiftUI foundation.
- Projects requiring protocol-oriented DI + actor-backed persistence.






