Data Flow: ObservableObject & Environment

June 02, 2026 1 min read

For data shared across views, use a class conforming to ObservableObject with @Published properties.

A view model

class CartModel: ObservableObject {
    @Published var items: [Item] = []
    func add(_ item: Item) { items.append(item) }
}

Owning vs observing

  • @StateObject — the view that creates/owns the object.
  • @ObservedObject — a view that receives it from a parent.
  • @EnvironmentObject — inject once, read anywhere down the tree.
@main
struct MyApp: App {
    @StateObject private var cart = CartModel()
    var body: some Scene {
        WindowGroup { ContentView().environmentObject(cart) }
    }
}
// deep child: @EnvironmentObject var cart: CartModel
Common mistake: Create an ObservableObject with @StateObject exactly once (at its owner). Using @ObservedObject to create it can lose data on redraws.

Summary

ObservableObject + @Published shares state. Own it with @StateObject, receive it with @ObservedObject, or broadcast it with @EnvironmentObject.