State vs Binding: A Mental Model
The confusion
One of the first recurring questions in SwiftUI is deceptively simple:
“Should this be
@Stateor@Binding?”
You see both used everywhere. Examples work. Previews compile. And yet, as soon as a view grows or gets reused, things start to feel wrong.
Bindings appear where you don’t expect them. State seems to “leak” through your view hierarchy. Refactoring suddenly becomes painful.
The confusion is not about syntax. It’s about ownership.
Why this is confusing
SwiftUI encourages composition: small views, passed around freely, nested deeply.
At the same time, SwiftUI also hides a lot of lifecycle details. Views are value types. Bodies are recomputed. State lives somewhere else.
That makes it easy to accidentally treat @State and @Binding as interchangeable,
instead of seeing them for what they actually represent.
Most confusion comes from asking the wrong question:
“Which property wrapper should I use here?”
That question is already too late.
A better mental model
Here is the mental model that removes 90% of the confusion:
@State owns data.
@Binding borrows data.
That’s it.
Not:
- “Use
@Statein parent views” - “Use
@Bindingin child views” - “Use
@Bindingwhen passing data”
Those are patterns, not principles.
The principle is ownership.
A small proof
Consider the simplest possible example:
struct CounterView: View {
@State private var count = 0
var body: some View {
Button("Count: \(count)") {
count += 1
}
}
}
This view:
- creates the state
- owns the state
- decides how it changes
Now extract the button:
struct CounterButton: View {
@Binding var count: Int
var body: some View {
Button("Count: \(count)") {
count += 1
}
}
}
Nothing about the behavior changed. What changed is responsibility.
CounterButton does not own count.
It only operates on something it was given.
That is exactly what a binding represents.
Why this matters in real apps
Once you internalize ownership, several things become easier immediately:
- Refactoring You can move views around without redesigning state flow.
- Reuse Views that use bindings are easier to reuse because they make fewer assumptions.
- Architecture State naturally rises to the place where it is actually owned.
You stop fighting SwiftUI’s data flow and start working with it.
Where this mental model breaks down
No mental model is perfect.
Some edge cases still require thought:
@StateObjectvs@ObservedObject@Environmentvalues- Derived state computed from multiple sources
But even there, ownership remains the right first question.
If you start by asking who owns this data, the correct abstraction usually reveals itself.
One sentence to remember
State lives where it is owned. Bindings exist only to pass ownership boundaries.