Reference
How state works
Every modern app UI works the same way: the screen is computed from a piece of state, and you change the screen by changing that state. Get this model and a whole category of bugs — the stale value, the two copies that disagree — simply disappears. Here are the ideas the lab drills. Open the state lab →
- The screen is a function of state
You never edit the screen directly. The view reads the current state and produces the screen. Same state → same screen; change the state → the screen recomputes.
- An event changes state, not the screen
A tap runs an action that returns a new state. Then the view re-reads that state and the screen updates. The button doesn’t “set the label” — it changes a value the label reads.
- Derive, don’t store
If a value can be computed from other state (a total from price × count, a “remaining” from goal − done), COMPUTE it on every render. A stored copy has to be kept in sync by hand — and one day you forget, and it goes stale.
- A stored copy is a stale copy waiting to happen
Storing a derived value means every place that changes an input must re-sync it. Miss one path and the screen shows an old value. Deriving removes the whole class of bug — there’s nothing to forget.
- Lift state up to one owner
When two parts of a screen must agree, they can’t each keep their own copy — they’ll drift. Lift that state up to ONE place both read from. One source of truth is the same idea as derive-don’t-store, for shared state.
- Read the view as a description, not a drawing
A declarative view describes WHAT should show for a given state (an if row appears when its condition is true). To predict the screen, evaluate the view against the state — top to bottom.
The reasoning moves
- Predict the screen
Read the struct, then walk the view top-to-bottom — an if row shows only when its condition is true; \(var) reads the value.
- Predict after an event
Apply the tapped action to the state, then re-read the view against the NEW state.
- Spot the stale value
After an event, does a stored field still equal what it’s supposed to (total == price × count)? If not, it’s stale.
- Derive it
Replace the stored field with a computed one (Total: \(price * count)). Correct after any event, forever.
The puzzles are original teaching examples in a teaching subset of the Swift language — a teaching dialect, not SwiftUI. Nothing you read leaves your device. Read a puzzle →