@Observable modelsThese are the lesson notes for this day. Its build-along tutorial and flash cards have not been written yet.
@Observable modelsFor data that lives outside a single view — a model shared across several screens — write a class and mark it @Observable. SwiftUI records which properties each view's body actually reads, and re-renders a view only when one of those properties changes. A view that creates and owns the model keeps it in @State. Views that are handed the model simply declare an ordinary property. To get bindings to a model's properties, wrap it with @Bindable.
@Observable arrived in iOS 17. It replaces the older system of ObservableObject, @Published, @StateObject and @ObservedObject, which was built on Combine and re-rendered every observing view whenever anything changed. You will still meet the old form in existing code, so you need to be able to read it and to migrate it. Since iOS 26, Observations gives you an AsyncSequence of changes, for watching a model from outside a view.
@Observable
final class TripStore {
var trips: [String] = []
var isSyncing = false
}
struct TripsScreen: View {
@State private var store = TripStore() // the owner keeps the model in @State
var body: some View {
TripCount(store: store) // children simply receive it
}
}
struct TripCount: View {
let store: TripStore
// This body reads `trips` only, so changing `isSyncing` does not re-render it.
var body: some View {
Text("\(store.trips.count) trips")
}
}
Exercise
Create an @Observable model with two properties and two views that each display one of them. Add a print to each body and prove that changing one property re-renders only one view. Then convert a class that uses ObservableObject and @Published to @Observable.
@Observable object changes?@Observable model that it owns, and how does a child view get a binding to one of its properties?@Observable replace, and what was the drawback of the older system?