In SwiftUI, StateObject and ObservedObject are both property wrappers used to manage state in your views, but they have different lifecycles and use cases.
Use StateObject when the view is the source of truth for the object. It’s created by the view and should be tied to the view’s lifecycle. The object is retained by the view across redraws, preserving its state.
Use ObservedObject when the object’s lifecycle is managed outside the view, such as when it’s passed into the view. The object may be recreated when the view is redrawn, which can lead to loss of state if not handled properly.
import SwiftUI
import Combine
class Counter: ObservableObject {
@Published var count: Int = 0
func increment() {
count += 1
}
func decrement() {
count -= 1
if count < 0 {
count = 0
}
}
}
struct CounterView: View {
@ObservedObject var counter: Counter
var body: some View {
VStack {
HStack {
Button("-") {
counter.decrement()
}
Button("+") {
counter.increment()
}
}
}
}
}
struct ContentView: View {
@StateObject private var counter = Counter()
var body: some View {
VStack {
CounterView(counter: counter)
Text("Count: \(counter.count)")
}
}
}
With the introduction of the new Observation framework since iOS 17, StateObject and ObservedObject are being phased out in favor of new property wrappers that integrate more seamlessly with the updated SwiftUI data flow.