SwiftAtlas is an iPhone-first SwiftUI reference application built to teach Swift and modern iOS engineering through production-style code. The app is intentionally structured so the codebase itself is the lesson: architecture, state ownership, concurrency, caching, design systems, previews, testing, memory management, and secure storage are all demonstrated in working features rather than in isolated snippets.
The project uses Apple frameworks only, follows MVVM with explicit boundaries, and favors readable, teachable code over shortcuts or abstraction for its own sake.
Operational setup, build, test, formatting, and debugging instructions live in RUNBOOK.md.
- Every repository and view model should have deterministic unit tests.
- Every non-trivial screen should include multiple previews that demonstrate meaningful states.
- User-visible strings should be represented in
Localizable.xcstrings. - UI tests should cover at least one critical journey for each top-level area of the app.
- Teach Swift and iOS app architecture through a real application.
- Provide a clean MVVM reference with explicit separation between views, view models, repositories, and shared infrastructure.
- Demonstrate modern SwiftUI patterns for local state, global state, navigation, reusable components, previews, and testing.
- Show production-grade concerns such as networking, caching, diagnostics, feature flags, secrets storage, ARC, retain cycles, and structured concurrency.
- Keep the codebase approachable enough to study file by file.
The app is organized around four tabs:
Home: architecture summary, app purpose, high-level diagnostics, and quick links into the learning areas.Lessons: API-backed content demonstrating lists, grouping, filtering, detail flows, refresh, caching, and pinned state.Labs: focused demos for components, theming, modals, ownership, inheritance, access control, and concurrency.Settings: theme override, feature flags, diagnostics, cache management, and Keychain-backed secret storage.
This repository is designed to act as a practical reference for the following topics:
- MVVM and project structure
- SwiftUI state ownership
- Global app state versus feature-local state
- Dependency injection through a container
- Design tokens, theme resolution, dark mode, and reusable components
- Networking with
URLSessionand app-owned request/response types - DTO-to-domain mapping
- In-memory and disk-backed caching
- Search, list rendering, grouping, and modal presentation
- Keychain-backed secret storage
- Memory management, ARC, strong/weak/unowned references, and retain cycles
- Inheritance, subclassing, override control,
final, and protocol-first tradeoffs - Access control and special identifiers
- Structured concurrency,
Task,async let, cancellation, and actor-based isolation - Sample data, previews, deterministic test fixtures, unit tests, and UI tests
SwiftAtlas uses a layered MVVM structure:
View -> ViewModel -> Repository / Service -> Infrastructure
The core rule is that SwiftUI views render and bind state, but they do not contain business logic. View models orchestrate feature behavior. Repositories and services perform data access, mapping, persistence, and side effects. Shared infrastructure stays behind stable interfaces.
- Feature-local state lives in feature view models.
- App-wide state lives in
AppState. - Dependencies are resolved through
AppContainer. - Shared mutable infrastructure is kept explicit rather than hidden behind global singletons.
The app container wires together the main runtime dependencies:
AppStateLessonRepositoryExerciseRepositoryFeatureFlagStoreSecretsStoreCacheStorePinnedLessonStoreDiagnosticsService
See AppContainer.swift.
The app starts in SwiftAtlasApp.swift, builds a live container, and injects it into the SwiftUI environment. The tab shell lives in AppScene.swift.
SwiftAtlas/
App/
Core/
Architecture/
DesignSystem/
Foundation/
Networking/
Persistence/
Features/
Home/
Lessons/
Labs/
Settings/
Shared/
Models/
PreviewSupport/
SampleData/
Services/
Resources/
SwiftAtlasTests/
SwiftAtlasUITests/
- SwiftAtlasApp.swift: app entry point
- AppScene.swift: root tab UI
- AppState.swift: global app state
- AppRouter.swift: app tab metadata
Architecture: feature flags and loadable stateDesignSystem: tokens, theme resolution, and reusable UI componentsFoundation: app errors, diagnostics, build metadataNetworking: requests, endpoints, DTOs, and HTTP clientPersistence: cache stores and secret storage
Home: top-level educational dashboardLessons: remote data flow, search, grouping, pinned lessons, detail viewsLabs: focused technical demonstrationsSettings: app configuration and diagnostics
- domain models owned by the app
- preview containers and fake repositories
- deterministic sample data
- small cross-feature services such as pinned lessons
The app maps JSONPlaceholder into app-owned domain types so the UI is never coupled directly to transport models.
The app uses JSONPlaceholder as a read-only demo backend:
users-> track owners and mentor metadataposts-> lessonstodos-> exercisescomments-> lesson discussions/examples
The main domain types live under Shared/Models:
TrackTrackOwnerLessonLessonGroupLessonDetailLessonCommentExerciseLabTopicComponentExampleAppNoticeNetworkReachabilityState
This is a deliberate teaching choice: transport models are implementation details, domain models are application language.
The app has a small design system rather than ad hoc view styling.
Tokens live under Core/DesignSystem/Tokens:
GSColorTokensGSSpacingGSTypography
These provide semantic building blocks so feature views do not hardcode styling decisions repeatedly.
Theme support lives under Core/DesignSystem/Theme:
ThemeOptionThemePaletteThemeResolver
Supported theme modes:
systemlightdark
The selected theme is stored in app state and is applied globally using preferredColorScheme.
Reusable components live under Core/DesignSystem/Components:
GSCardGSSectionHeaderGSPrimaryButtonGSSecondaryButtonGSAsyncStateViewGSBadgeGSInfoRowGSErrorViewGSSkeletonBlockGSToggleRow
These are intentionally simple enough to study and reuse, but structured enough to model good boundaries and semantic styling.
The Lessons feature is the main end-to-end example of the app’s data layer.
Networking infrastructure lives under Core/Networking:
APIRequestHTTPClientURLSessionHTTPClientJSONPlaceholderAPI- JSONPlaceholder DTO types
The app uses URLSession behind an HTTPClient protocol so production code, previews, and tests can swap implementations cleanly.
The repository layer maps DTOs into domain types before they reach views. See DefaultLessonRepository.swift.
Notable patterns shown there:
async letfor parallel network requests- cache-first reads for fast initial rendering
- detail fetch composition
- DTO-to-domain mapping
- separation between remote payloads and feature models
Caching support lives under Core/Persistence/Cache:
CachePolicyCacheKeyCacheStoreInMemoryCacheStoreJSONFileCacheStore
Supported policies:
remoteOnlycacheOnlycacheFirststaleWhileRevalidate
The repository layer uses these policies to decide whether to serve cached data, fetch remotely, or do both in sequence.
Secrets are handled through a dedicated abstraction:
The Settings feature includes a demo token flow so the project can teach:
- why secrets should not go into
UserDefaults - how to hide security implementation details behind a protocol
- how to test secret storage with an in-memory fake
Feature flags live under Core/Architecture/FeatureFlag:
FeatureFlagFeatureFlagStoreUserDefaultsFeatureFlagStore
This supports:
- default values in code
- local overrides
- testable flag lookups
- settings-driven toggles
The Lessons feature is the strongest example of the app’s main architectural path.
Key files:
Concepts demonstrated:
- loading and empty states
- grouped list rendering
- pull-to-refresh
- search
- pinned items
- detail fetch and mapping
- exercise grouping
- cache-backed reads
The Labs tab contains explicit teaching demos that are valuable even if they are not part of the core content product flow.
These demonstrate reusable UI, semantic styling, and presentation APIs.
These files demonstrate:
- ARC fundamentals
- strong references
weakreferencesunownedreferences- object-to-object retain cycles
- object-to-closure retain cycles
- deallocation visibility
This covers final, override, required init, private(set), class vs static, and protocol-first alternatives.
This covers:
privatefileprivateinternalpublicopenselfSelfsuper#function#fileID#line#column
This demonstrates:
Task- cancellation-aware work
- actor-based mutation
@MainActorUI coordination- explicit async orchestration
The Settings flow is where most app-wide controls live.
Key files:
- SettingsViewModel.swift
- AppearanceSettingsView.swift
- FeatureFlagsView.swift
- SecretsDemoView.swift
- CacheInspectorView.swift
- DiagnosticsView.swift
This feature demonstrates:
- persisted theme changes
- feature flag toggles
- Keychain-backed secret handling
- cache clearing
- diagnostics snapshots
- app-level notices
Preview support lives under Shared/PreviewSupport and Shared/SampleData.
Key ideas:
- deterministic sample data
- preview containers with fake dependencies
- feature-level preview wiring without touching live infrastructure
- reproducible visual states for teaching and regression catching
Important preview support files:
PreviewContainerPreviewAppContainerPreviewRepositoriesPreviewScenariosSampleLessonsSampleExercisesSampleFlagsSampleThemeState
The project uses a mix of the modern Testing framework and UI tests.
Unit and integration coverage currently includes:
- repository mapping
- lesson view model behavior
- feature flag logic
- in-memory secrets storage
- ownership/ARC behavior
- concurrency lab behavior
See:
- LessonRepositoryTests.swift
- LessonListViewModelTests.swift
- FeatureFlagStoreTests.swift
- InMemorySecretsStoreTests.swift
- OwnershipLabTests.swift
- ConcurrencyLabTests.swift
UI tests live under SwiftAtlasUITests.
Current UI coverage includes:
- app launch
- basic flow validation
See:
- Xcode with iOS SDK support
- iOS simulator runtime or a physical device
- macOS environment capable of running
xcodebuild
Open SwiftAtlas.xcodeproj and run the SwiftAtlas scheme on an iPhone simulator or device.
xcodebuild -project SwiftAtlas.xcodeproj \
-scheme SwiftAtlas \
-destination 'generic/platform=iOS' \
-derivedDataPath /tmp/SwiftAtlasDerivedData \
CODE_SIGNING_ALLOWED=NO \
buildUnit and UI tests can be run from Xcode or the command line. Example:
xcodebuild -project SwiftAtlas.xcodeproj \
-scheme SwiftAtlasTests \
-destination 'platform=iOS Simulator,name=iPhone 16' \
testxcodebuild -project SwiftAtlas.xcodeproj \
-scheme SwiftAtlasUITests \
-destination 'platform=iOS Simulator,name=iPhone 16' \
testNote: in restricted environments, simulator-backed test execution may fail if CoreSimulator services are unavailable even when the project itself builds cleanly.
The repo rules are captured in AGENTS.md. The most important conventions are:
- MVVM boundaries are strict.
- Views stay thin.
- Domain models are app-owned.
finalis the default for classes.- Shared mutable state must be explicit.
- Theme tokens should be used instead of hardcoded styling.
- Every meaningful change should consider previews and tests.
If you are using the project to learn Swift or iOS engineering, this order works well:
- Start with SwiftAtlasApp.swift, AppScene.swift, and AppContainer.swift.
- Read the shared domain models in Shared/Models.
- Follow the Lessons feature from view to view model to repository.
- Inspect the design system components and theme tokens.
- Study the Labs feature for focused language and runtime concepts.
- Read the tests to see how the architecture is exercised in isolation.
There are many sample projects that show isolated APIs, but fewer that show how those APIs fit together in a disciplined, readable application. SwiftAtlas exists to fill that gap. It is meant to be a durable teaching codebase you can browse when you want a concrete answer to questions like:
- How should I structure an MVVM SwiftUI app?
- Where should state live?
- How do I map network DTOs into domain models?
- How should I handle cache layers and feature flags?
- What does good preview infrastructure look like?
- How do I reason about
weak,unowned, retain cycles, andfinalin real code? - How should I organize tests in a modern Swift codebase?
The project is already organized as a working iOS app with app, unit-test, and UI-test targets. The architecture and teaching coverage are in place, and the codebase is designed to support continued expansion without changing its core structure.