Loading...

@StateObject vs @ObservedObject in SwiftUI

question swiftui swift
Ram Patra Published on August 31, 2024

In SwiftUI, both @StateObject and @ObservedObject are property wrappers used to manage state in your views, specifically when working with objects that conform to the ObservableObject protocol. However, they serve slightly different purposes and have different use cases. Here’s a breakdown:

@StateObject

  • Purpose: Use @StateObject when you want to own the state of an ObservableObject. It ensures that the object is created once during the view’s lifecycle and is retained by the view.
  • Usage: Typically, you use @StateObject in the view where the ObservableObject is first created. The view that owns the @StateObject will manage its lifecycle, including its creation, updates, and destruction.
  • Example:
    class MyViewModel: ObservableObject {
        @Published var count = 0
    }
    
    struct MyView: View {
        @StateObject private var viewModel = MyViewModel()
          
        var body: some View {
            Text("Count: \(viewModel.count)")
            Button("Increment") {
                viewModel.count += 1
            }
        }
    }
    

    In this example, MyView owns the MyViewModel instance, which will persist as long as MyView is alive.

@ObservedObject

  • Purpose: Use @ObservedObject when you want to observe an ObservableObject that is owned elsewhere. It allows a view to react to changes in an ObservableObject, but the view does not manage its lifecycle.
  • Usage: Typically used when you pass an existing ObservableObject down the view hierarchy. The object is created and owned by another view, and you’re just observing changes to it.
  • Example:
    struct ParentView: View {
        @StateObject private var viewModel = MyViewModel()
          
        var body: some View {
            ChildView(viewModel: viewModel)
        }
    }
    
    struct ChildView: View {
        @ObservedObject var viewModel: MyViewModel
          
        var body: some View {
            Text("Count: \(viewModel.count)")
        }
    }
    

    Here, ParentView owns the viewModel using @StateObject, and ChildView observes it using @ObservedObject. If ParentView goes away, the viewModel will be destroyed as it is not owned by ChildView.

Key Differences

  1. Ownership:
    • @StateObject: View owns the ObservableObject.
    • @ObservedObject: View does not own the ObservableObject; it observes an external one.
  2. Lifecycle Management:
    • @StateObject: Manages the lifecycle (creation, retention, and destruction) of the ObservableObject.
    • @ObservedObject: Depends on the lifecycle of an external ObservableObject.
  3. Use Cases:
    • @StateObject: Use in views where the object is first created or owned.
    • @ObservedObject: Use in views that just need to observe an existing object passed from elsewhere.

Practical Example

When you want to create a view model in a view and keep it alive as long as the view is alive, use @StateObject. When a child view is interested in reacting to changes in a view model that it doesn’t create, use @ObservedObject.

Understanding when to use @StateObject versus @ObservedObject is key to managing state effectively in SwiftUI applications.

Presentify

Take your presentation to the next level.

FaceScreen

Put your face and name on your screen.

KeyScreen

Show keypresses on your screen.

ToDoBar

Your to-dos on your menu bar.

SimpleFill

Fill forms using your right-click menu.

IconSim

Preview your Mac app icons.

Ram Patra Published on August 31, 2024
Image placeholder

Keep reading

If this article was helpful, others might be too

question swiftui swift September 7, 2024 How to apply mirroring to any SwiftUI view?

You can apply mirroring to a SwiftUI view by using the scaleEffect(x:y:anchor:) modifier to flip the view horizontally or vertically. Specifically, you can set the x or y scale to -1.0 to mirror the view along that axis.

question swiftui swift February 19, 2025 How to change the window level to floating, popUpMenu, etc. in SwiftUI?

When developing macOS applications with SwiftUI, you might need to create floating windows that stay on top of other windows. While modern macOS versions (15+) make this straightforward with the .windowLevel(.floating) modifier, supporting older versions requires a different approach. In this post, I’ll show you how to create floating windows that work across different macOS versions.

question swiftui macos September 3, 2024 How to open and close windows programmatically in SwiftUI?

To open or close a window programmatically from outside that window using environment variables, you need to leverage the new openWindow (macOS 13+) and dismissWindow (macOS 14+) environment variables. This environment variables allow you to programmatically open and close a window by its identifier.

Like my work?

Please, feel free to reach out. I would be more than happy to chat.