@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.