Fix the 'Modifying state during view update' runtime warning
The view below prints "Modifying state during view update, this will cause undefined behavior" at runtime. It assigns a @State value inside body.
Requirements:
- Explain what makes the mutation illegal during view evaluation.
- Move the write out of the render pass so the value is still set correctly.
struct CounterView: View {
@State private var count = 0
let start: Int
var body: some View {
count = start // fires the warning
return Text("Count: \(count)")
}
}
Find and fix the bug.
It happens when body mutates observed state while SwiftUI is still computing that body — assigning a @State value during evaluation. Move the mutation out of the render pass into .onAppear, .task, .onChange, or a user action.
- ✗Assigning
@State/@Publishedvalues directly insidebody - ✗Thinking
DispatchQueue.main.asyncaround the write fixes the root cause - ✗Treating the warning as harmless instead of a real re-entrancy bug
- →Why is mutating observed state during
bodyevaluation undefined? - →Which modifier would you use to run the mutation after the view appears?
body must be a pure function of state — it reads state to describe the view and must not write it. Assigning count = start while SwiftUI is evaluating body re-enters the update cycle (the write schedules another invalidation from inside the current one), which is the undefined behavior the warning names.
Move the write to a lifecycle hook that runs after the view is built, so it is not a side effect of rendering:
struct CounterView: View {
@State private var count = 0
let start: Int
var body: some View {
Text("Count: \(count)")
.onAppear { count = start } // runs after body, outside the render pass
}
}
If the value only needs to depend on start, initializing it once (@State private var count: Int set in init) or using .onChange(of: start) are equally valid — the rule is simply: never assign state as part of computing body.