Capstone: A Working Small SwiftUI App
iOS Development Fundamentals
Chapter 10 · Capstone: A Working Small SwiftUI App
Nine chapters have each built one working piece in isolation — a counter, a badge, a list of tasks, a fetched quote. This capstone wires every one of them together into a single, genuinely working small app: TaskFlow — a task tracker with a real quote-of-the-day header, a task list, a detail screen, and a form for adding new tasks.
| Chapter | What It Contributes to TaskFlow |
|---|---|
| 1 — Why iOS Development | The @main app struct, WindowGroup, real App/View protocol conformance throughout |
| 2 — Swift Basics & Optionals | String interpolation; Quote? as a real optional, unwrapped with if let |
| 3 — Control Flow, Functions & Closures | A switch for priority labels; trailing closures for every Button |
| 4 — Structs, Classes & Value/Reference | Task as a value-type struct; TaskStore as a shared reference-type class |
| 5 — SwiftUI Fundamentals | Modifiers styling TaskRow's priority badge |
| 6 — State Management | @State for local form fields, @Observable/@Bindable for the shared TaskStore |
| 7 — Layout: Stacks, Lists & ScrollViews | List + ForEach over store.tasks, using Task's own Identifiable conformance |
| 8 — Navigation & Multi-Screen Apps | NavigationStack, NavigationLink(value:) + navigationDestination, .sheet() for adding a task |
| 9 — Forms & Basic Networking | A real Form for the new-task sheet; async/await + URLSession + .task for the quote header |
File Structure
The Model: Task and TaskStore
Task is a real value-type struct (Chapter 4) — cheap, safe to copy, conforming to
Identifiable and Hashable for List and navigation (Chapters 7-8).
TaskStore is a real, shared reference-type class, marked @Observable
(Chapter 6) so every view holding it stays in sync automatically.
The Quote Header
Chapter 9's own fetch pattern, applied to a "quote of the day" shown above the task list — a real
Quote? optional (Chapter 2), unwrapped with if let, populated by
.task {}.
The Task Row
A real switch statement (Chapter 3) turns a priority number into a label, and Chapter 5's own
modifiers style it into a small badge.
The Task List, Navigation & Add Sheet
This is the capstone's own central piece — everything from Chapters 6-8 in one view: a shared
@Bindable TaskStore, a real List with sections, value-based
navigation into a detail screen, and a modal .sheet() for adding a task.
@ObservableTaskListView, TaskDetailView, and NewTaskView all hold the exact
same real TaskStore instance — because it's a reference type (Chapter 4), adding a task in
NewTaskView or toggling one in TaskDetailView is instantly visible back in
TaskListView's own List, with no manual "refresh" step anywhere. This is the
genuine, concrete reason Chapter 6 reached for a class here instead of a struct.
The Detail Screen & New Task Form
NewTaskView is a real Form (Chapter 9), and closes itself via
@Environment(\.dismiss) — a real, built-in SwiftUI environment value that dismisses whichever
presentation (here, the .sheet()) currently owns the view.
Tying It Together
Running this in the Simulator (Chapter 1) shows a real, working task tracker: the quote loads in the
background while the list appears immediately, tapping a task pushes its detail screen (Chapter 8),
toggling "Mark as Done" updates the row instantly back on the list (thanks to the shared
@Observable store), and the "Add" button presents a real form for creating a new task.
Hands-On Exercises
Add a func delete(at offsets: IndexSet) method to TaskStore that removes tasks at the given offsets, and wire it into TaskListView's own ForEach via the real .onDelete(perform:) modifier, enabling real swipe-to-delete.
Change TaskDetailView so it also shows the priority label from TaskRow, then add a validation rule to NewTaskView's own "Save" button disabling it (using the real .disabled() modifier) whenever title is empty, rather than silently doing nothing on tap.
Explain, in your own words, why TaskListView, TaskDetailView, and NewTaskView all being handed the exact same TaskStore instance — rather than three separate copies — is what makes toggling a task's done state in one screen instantly visible in another, tying your answer back to Chapter 4's own value-type/reference-type distinction.
Where to Go From Here
TaskFlow deliberately stays small — no persistence (tasks vanish on relaunch), no real backend behind
fetchQuote(), no automated tests. Every one of those is genuine iOS Development —
Architecture & Data territory: MVVM architecture, structured concurrency beyond a single
.task {}, SwiftData for real local persistence, dependency injection, and unit
testing with Swift Testing — the direct next course in this three-course arc.
What TaskFlow Demonstrates
- The App/View protocol structure and Simulator workflow (Ch1)
- Optionals, string interpolation (Ch2),
switchand trailing closures (Ch3) Taskas a value-type struct,TaskStoreas a shared reference-type class (Ch4)- Real SwiftUI views and modifiers styling a priority badge (Ch5)
@State,@Observable, and@Bindablekeeping three separate screens in sync (Ch6)List/ForEachoverIdentifiabledata (Ch7)NavigationStack, value-based navigation, and a modal.sheet()(Ch8)- A real
Form, plusasync/awaitnetworking via.task {}(Ch9)