The capstone is a small article reader app. It is intentionally modest, but it uses the same patterns as larger SwiftUI apps.
App goal
Build an app that:
- loads a list of articles from JSON
- shows loading, success, and error states
- displays article details
- lets the user favorite articles
- persists favorite article IDs
- keeps networking and persistence out of views
Model the data first
struct Article: Identifiable, Codable {
let id: String
let title: String
let summary: String
let body: String
let authorName: String
}
enum ArticleListState {
case idle
case loading
case loaded([Article])
case failed(message: String)
}
The enum prevents unclear combinations like “loading and failed and loaded.”
Separate responsibilities
Use small types with clear jobs:
Article.swift model
ArticleService.swift network fetch and decode
FavoritesStore.swift persisted favorite IDs
ArticleListViewModel.swift state and user actions
ArticleListView.swift list UI
ArticleDetailView.swift detail UI
ArticleRow.swift reusable row
This structure keeps each file understandable.
Data flow
One practical flow:
ArticleListViewappears..taskcallsawait viewModel.load().- View model asks
ArticleServicefor articles. - Service fetches data and decodes
[Article]. - View model publishes
ArticleListState. - View renders loading, list, or error UI.
- User taps favorite.
- View model updates
FavoritesStore.
The view does not know how networking or persistence works. It only renders state and sends actions.
What success looks like
By the end, you should be able to explain:
- why models are structs
- why loading state is an enum
- where optionals are appropriate
- where errors are appropriate
- why async work is visible in function signatures
- which view owns state
- which views receive bindings or values
- how favorite IDs persist
What to carry forward
- build apps from clear models outward
- use enums for important state machines
- keep side effects in services and stores
- keep views focused on rendering and actions
- prefer explicit data flow over hidden shared state
- small apps can practice production habits
You now have the core Swift foundation needed to keep learning SwiftUI and building real Apple-platform apps.