@State & @Binding
SwiftUI views are value types , so how can they change? The answer is property wrappers . @State gives a view its own mutable source of truth, and @Binding lets a child read and write state that a parent owns. Master these and your UIs come alive.
Learn @State & @Binding in our free Swift course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Swift course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Building iOS Apps with SwiftUI • Intermediate
What You'll Learn in This Lesson
1️⃣ @State — A View's Own Source of Truth
Mark a property with @State to give the view a small piece of mutable data it owns. SwiftUI stores that value for you (outside the struct) and watches it. When you change it, SwiftUI re-runs body and redraws. Keep it private — it belongs to this view alone.
2️⃣ @Binding — Sharing Writable State
When a child view needs to read and write state owned by a parent , use @Binding . It's a two-way connection: the parent keeps the single source of truth, but the child can update it. You hand the child a binding using the $ prefix on the parent's @State .
3️⃣ The $ Prefix — Projected Values
Every property wrapper can expose a projected value via the $ prefix. For @State and @Binding , the projected value is a Binding . Use the plain name for the value, and $name when a control like TextField must write back.
Your turn. Fill in the blanks to wire up local state and pass a binding to a child.
Build a parent view that owns an @State quantity starting at 1. Create a child QuantityStepper that takes a @Binding var quantity: Int and shows "−" and "+" buttons that decrease and increase it. Pass the state down with $ , and show the live total in the parent.
Practice quiz
What does the @State property wrapper provide?
- A shared global value
- Local mutable state owned by a view
- A database connection
- A constant value
Answer: Local mutable state owned by a view. @State gives a view its own piece of mutable state that SwiftUI stores and watches for changes.
What happens when an @State value changes?
- Nothing until you call refresh()
- SwiftUI re-computes the view's body
- The app crashes
- The value is discarded
Answer: SwiftUI re-computes the view's body. Changing @State invalidates the view, so SwiftUI re-runs body and updates the screen.
Why is @State usually marked private?
- It is required by the compiler
- Because it is local source of truth owned by that view
- To make it global
- It cannot be private
Answer: Because it is local source of truth owned by that view. @State is the view's own source of truth, so it's conventionally private to that view.
What does @Binding create?
- A copy of a value
- A constant
- A new source of truth
- A two-way connection to state owned elsewhere
Answer: A two-way connection to state owned elsewhere. @Binding is a read-write reference to state that lives in a parent view, enabling two-way data flow.
How do you pass an @State value as a binding to a child?
- By writing state.binding
- By prefixing the name with a dollar sign, like $name
- By using @Binding twice
- You cannot pass it
Answer: By prefixing the name with a dollar sign, like $name. The $ prefix (projected value) turns an @State into a Binding you can hand to a child view.
Inside a child, what does the plain binding name (without $) give you?
- The current underlying value
- The Binding wrapper itself
- Always nil
- A copy that won't update
Answer: The current underlying value. Reading a @Binding by its name yields the underlying value; writing to it updates the parent's state.
Why are SwiftUI views value types (structs)?
- So they can be subclassed
- To allow inheritance
- So SwiftUI can cheaply create and diff them
- Because classes are banned
Answer: So SwiftUI can cheaply create and diff them. Views are lightweight structs, so SwiftUI can recreate and compare them efficiently every update.
Since a view is a struct, why can its body still 'mutate' a counter?
- Structs are secretly classes
- @State stores the value outside the struct so SwiftUI manages it
- It does not actually change
- Swift copies the whole view
Answer: @State stores the value outside the struct so SwiftUI manages it. @State stores its value in storage managed by SwiftUI, not in the struct itself, so updates persist across recreations.
Which declaration is correct for a counter starting at 0?
- @State var count = 0
- @Binding var count = 0
- @State let count = 0
- var @State count = 0
Answer: @State var count = 0. @State var count = 0 declares mutable local state with an initial value.
When should you use @Binding instead of @State?
- Always, they are identical
- When the child needs to read AND change state owned by a parent
- Only for constants
- Never in SwiftUI
Answer: When the child needs to read AND change state owned by a parent. @Binding is for a child view that must read and write state whose source of truth lives in a parent.