SwiftUI
ObservedObject
StateObject
Swift programming
iOS development

What is the difference between ObservedObject and StateObject in SwiftUI

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

@ObservedObject and @StateObject both connect a SwiftUI view to an ObservableObject, but they differ in ownership and lifetime. That is the core distinction. If the view owns and creates the object, use @StateObject. If the object is created elsewhere and merely passed in, use @ObservedObject.

Use @StateObject When the View Owns the Object

A @StateObject is initialized once for the lifetime of that view identity and kept alive by SwiftUI.

swift
1import SwiftUI
2
3final class CounterModel: ObservableObject {
4    @Published var count = 0
5}
6
7struct CounterScreen: View {
8    @StateObject private var model = CounterModel()
9
10    var body: some View {
11        VStack {
12            Text("Count: \(model.count)")
13            Button("Increment") {
14                model.count += 1
15            }
16        }
17    }
18}

This is the right choice because CounterScreen creates the model and expects it to survive normal view redraws.

If you used @ObservedObject here instead, SwiftUI could recreate the object more often than you intended, leading to lost state.

Use @ObservedObject When Ownership Is External

An @ObservedObject is for a view that observes an object created elsewhere.

swift
1struct CounterPanel: View {
2    @ObservedObject var model: CounterModel
3
4    var body: some View {
5        Text("Count: \(model.count)")
6    }
7}
8
9struct ParentView: View {
10    @StateObject private var model = CounterModel()
11
12    var body: some View {
13        CounterPanel(model: model)
14    }
15}

Here the child view does not own the object. It just watches it. That is exactly what @ObservedObject is for.

The parent owns the lifetime. The child observes the updates.

The Wrong Wrapper Usually Shows Up as Reset State

A common bug is creating an observable object inside a view with @ObservedObject.

swift
1struct BadView: View {
2    @ObservedObject var model = CounterModel()
3
4    var body: some View {
5        Text("Count: \(model.count)")
6    }
7}

This compiles, but it creates the wrong ownership model. If SwiftUI recreates the view, the object can be recreated too, which leads to state resets or surprising lifecycle behavior.

That is the bug @StateObject was introduced to solve.

Think About Lifetime, Not Just Redraws

SwiftUI views are value types and are recreated frequently. Your object model often should not be. The property wrapper decides whether SwiftUI should preserve the observable object across view updates or simply subscribe to one supplied from somewhere else.

That is why the right mental model is not "which one updates the view." Both do that. The right mental model is "who owns this object and who is responsible for keeping it alive."

Parent-Child Structure Usually Makes the Choice Obvious

A good rule of thumb is:

  • root or owning view: @StateObject
  • dependent child view: @ObservedObject

That rule is not about hierarchy for its own sake. It is about having one clear owner.

If several views all think they own the same model, lifecycle bugs follow quickly.

@EnvironmentObject Is Yet Another Ownership Pattern

It helps to place these wrappers in context:

  • '@StateObject: this view owns the object'
  • '@ObservedObject: this view observes an externally owned object'
  • '@EnvironmentObject: the object is injected from the environment'

That comparison prevents a common confusion where developers treat @ObservedObject and @StateObject as if they were interchangeable update mechanisms.

Common Pitfalls

  • Creating an object inside a view with @ObservedObject instead of @StateObject.
  • Using @StateObject in a child view that does not actually own the model.
  • Thinking the wrappers differ in whether updates happen instead of in who owns the object.
  • Debugging random state resets without checking whether the object wrapper matches the intended lifetime.
  • Treating @ObservedObject, @StateObject, and @EnvironmentObject as synonyms.

Summary

  • Both wrappers observe ObservableObject changes, but they solve different ownership problems.
  • Use @StateObject when the view creates and owns the object.
  • Use @ObservedObject when the object comes from elsewhere.
  • The main symptom of using the wrong wrapper is unexpected object recreation and lost state.
  • In most parent-child designs, the parent owns with @StateObject and the child observes with @ObservedObject.

Course illustration
Course illustration

All Rights Reserved.