Introduction
Views are values, not objects
A SwiftUI view is a struct describing what should be on screen for the current state. It is not a
thing you hold and mutate — it is created, read and thrown away, many times a second.
struct Counter: View {
@State private var count = 0
var body: some View {
Button("Tapped \(count) times") { count += 1 }
}
}
Counter is recreated on every state change. That sounds expensive and is not: the struct is a few
bytes, and SwiftUI compares the new description with the old one to decide what actually needs
redrawing.
Tip
The mental shift that makes everything else click: you never tell SwiftUI to update. You change state, and the view is a function of that state. Any time you find yourself wanting to “refresh the view”, the state model is wrong.
The part nobody tells you
If a view were only a function of state, SwiftUI would be a template engine and this book would be a reference page. The interesting part is that the framework has to keep things across those thousands of discarded structs — where the cursor sits in a text field, how far a list is scrolled, which animation is halfway through — and your struct is long gone by the time any of that matters.
So there are two parallel worlds. The one you write is values: cheap, disposable, recreated constantly. The one SwiftUI maintains is a tree of long-lived storage nodes, and it decides which node belongs to which of your structs by their position and identity in the view tree.
Almost every SwiftUI bug that feels like witchcraft is a disagreement between those two worlds. The
text field that forgets what you typed, the animation that jumps instead of sliding, the @State
that resets when a parent redraws, the sheet that opens showing the wrong item — every one of them
is the framework matching a struct to a storage node you did not mean, or to a fresh one when you
expected the old.
That is the thread this book pulls on, and it is why the chapters are ordered the way they are rather than by API surface.
What this book covers
Views is about the tree itself: why composing beats configuring, what gives a view its identity, and why a modifier wraps rather than sets.
State and data flow is the ownership question — which of @State, @Binding, @Observable
and @Environment a value belongs in, and what each one costs when it changes.
Layout is the negotiation between a parent and its children: the proposal, the reply, and how to
read a layout that came out wrong. It ends by building a Layout of your own.
Animation is what happens between two states, why it attaches to a value rather than to a view, and what a transaction actually carries.
Performance is the measuring chapter — finding out which views redraw and why, instead of guessing.
What it assumes
That you know Swift. Structs, protocols, generics, closures and opaque return types are used without apology. If those are shaky, read Swift in Depth first — the two books are written to sit beside each other, and the chapter on values and references is the one this book leans on hardest.
It also assumes a recent SwiftUI: @Observable, NavigationStack and the Layout protocol are
treated as the normal way to do things rather than as new arrivals. Where an older API is still
worth knowing — usually because you will meet it in a codebase you did not write — it is named as
such rather than quietly ignored.
How to read it
In order, the first time. The chapters lean on each other more than the titles suggest: layout is hard to reason about before you know what identity means, and animation is unreadable before layout.
After that it is a reference, and each chapter is written to survive being read on its own.