Spot the bug, then pick the fix 2 steps
In this app, tapping Count works, but tapping Refresh sets the count back to 0. Which line causes it, and what is the fix?
Step 1 of 2: Find the bug
In this app, tapping Count works. Tapping Refresh sets the count back to 0. Tap the line that causes it.
@Observable final class CounterModel {var count = 0}struct CounterScreen: View {@State private var tick = 0var body: some View {VStack {Button("Refresh \(tick)") { tick += 1 }CounterCard()}}}struct CounterCard: View {var model = CounterModel()var body: some View {Button("Count: \(model.count)") { model.count += 1 }}}
Hint 1 of 2
What happens to CounterCard when tick changes?
Hint 2 of 2
Which property wrapper tells SwiftUI to keep state across view re-creation?
Step 2 of 2: Pick the fix
Line 16 makes a new model every time CounterCard is recreated. Which change fixes it?
Hint 1 of 1
Ownership is the issue, not observation.
Choose an answer, then open Show answer below to check it.
Show answer
Step 1: Find the bug
- Answer: line 16
var model = CounterModel()
CounterCard is a value that SwiftUI recreates every time CounterScreen.body runs. A plain stored property gets a brand-new CounterModel each time, so the count starts over. Nothing tells SwiftUI to keep it.
Step 2: Pick the fix
Answer: A @State private var model = CounterModel()
Correct. With @Observable, the owning view keeps the model in @State, and SwiftUI preserves it for the lifetime of that view's identity.
The view that creates an @Observable model owns it with @State, so SwiftUI keeps the same instance while the view keeps its identity.
Why not the others?
- B
@StateObject var model = CounterModel(). @StateObject requires ObservableObject. An @Observable class does not conform, so this does not compile. - C
@Bindable var model = CounterModel(). @Bindable only gives you bindings to an object you are handed. It does not own or preserve the object, so the reset still happens. - D Make
CounterModela struct. The @Observable macro only applies to classes.