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.