How to Use @ObservedObject in SwiftUI for Data Binding
Use
@ObservedObject in SwiftUI to connect a view to an external data model that conforms to ObservableObject. This lets the view automatically update when the model changes by observing its @Published properties.Syntax
The @ObservedObject property wrapper is used inside a SwiftUI view to observe an external data model that conforms to ObservableObject. The model must have properties marked with @Published to notify changes.
@ObservedObject var model: ModelClassdeclares the observed object.class ModelClass: ObservableObjectdefines the model.@Published var propertymarks properties that trigger UI updates.
swift
class Counter: ObservableObject { @Published var count = 0 } struct ContentView: View { @ObservedObject var counter: Counter var body: some View { Text("Count: \(counter.count)") } }
Example
This example shows a simple counter app where the view updates automatically when the count changes in the observed object.
swift
import SwiftUI class Counter: ObservableObject { @Published var count = 0 func increment() { count += 1 } } struct ContentView: View { @ObservedObject var counter = Counter() var body: some View { VStack(spacing: 20) { Text("Count: \(counter.count)") .font(.largeTitle) Button("Increment") { counter.increment() } } .padding() } } @main struct MyApp: App { var body: some Scene { WindowGroup { ContentView() } } }
Output
A screen showing "Count: 0" and a button labeled "Increment". Each tap on the button increases the count number displayed.
Common Pitfalls
- Not marking the model class with
ObservableObjectprevents updates. - Forgetting
@Publishedon properties means changes won't notify the view. - Using
@ObservedObjectfor a model created inside the view can cause unexpected behavior; prefer passing the model from a parent view. - Confusing
@ObservedObjectwith@StateObject: use@StateObjectwhen the view owns the model instance.
swift
class Model: ObservableObject { @Published var value = 0 // Fixed missing @Published } struct View: View { @ObservedObject var model = Model() // Model created here var body: some View { Text("Value: \(model.value)") } } // Correct way: class ModelCorrect: ObservableObject { @Published var value = 0 } struct ParentView: View { @StateObject var model = ModelCorrect() var body: some View { ChildView(model: model) } } struct ChildView: View { @ObservedObject var model: ModelCorrect var body: some View { Text("Value: \(model.value)") } }
Quick Reference
- @ObservedObject: Use in views to observe external ObservableObject models.
- ObservableObject: Protocol for data models that can be observed.
- @Published: Marks properties that trigger view updates.
- @StateObject: Use when the view owns the model instance.
Key Takeaways
Use @ObservedObject to connect a SwiftUI view to an external ObservableObject model.
Mark model properties with @Published to trigger UI updates when they change.
Use @StateObject when the view creates and owns the model instance, not @ObservedObject.
Passing the model from a parent view to child views with @ObservedObject keeps data in sync.
Forgetting ObservableObject or @Published prevents the view from updating automatically.