Why SwiftUI Recomposes Views (and Why That’s Fine)
The confusion
At some point, every SwiftUI developer notices something unsettling:
“Why is this view recomputed again?”
You add a print() statement.
You change a completely unrelated piece of state.
And suddenly, the view’s body runs again.
This often triggers fear:
- performance concerns
- accidental side effects
- the feeling that SwiftUI is doing “too much”
The confusion comes from assuming that recomputation means recreation.
It doesn’t.
Why this is confusing
In UIKit, views feel concrete. You create them, configure them, and they stay put until you change them.
SwiftUI looks similar on the surface, but behaves very differently underneath.
A SwiftUI View is:
- a value type
- lightweight
- disposable
Its body is not a rendering operation.
It is a description of the UI.
Recomputation is SwiftUI asking:
“Given the current state, what should the UI look like?”
That question is asked far more often than many developers expect.
A better mental model
Here is the key mental model:
SwiftUI views are values.
The UI is a result, not the view itself.
When state changes, SwiftUI does not mutate your views. It throws the old description away and asks for a new one.
Recomputation is not a bug. It is the core mechanism that keeps the UI correct.
If you treat body as a pure function of state, recomputation stops being scary.
A small proof
Consider this example:
struct CounterView: View {
@State private var count = 0
var body: some View {
print("Recomputing body")
return Button("Count: \(count)") {
count += 1
}
}
}
Every tap prints the message again.
Nothing is recreated permanently. SwiftUI simply reevaluates the description and updates the screen accordingly.
The work is cheap because:
- the view is a value
- rendering is diffed
- only the minimal UI changes are applied
Why this matters in real apps
Once you accept recomputation, several architectural decisions become clearer:
- Keep
bodycheap
Expensive work does not belong in view descriptions. - Move logic into the model layer
Views should describe, not decide. - Use modifiers declaratively
They describe intent, not execution order.
You stop fighting recomputation and start designing for it.
Where this mental model breaks down
Recomputation is cheap. Side effects are not.
Problems arise when:
- network calls live in
body - heavy calculations run during recomposition
- state changes trigger cascading updates
The model only holds if body stays pure.
When you need side effects, SwiftUI gives you explicit tools:
taskonAppearonChange
Use them consciously.
One sentence to remember
SwiftUI recomputes views because views are descriptions, not objects.
Design body as a pure function of state, and recomputation becomes your ally.