Use @Observable over @ObservableObject in iOS
Context
SwiftUI historically used @ObservableObject with @Published properties for state observation. The problem is it triggers view redraws for any @Published property change, even if the view doesn't use that property. It also requires verbose property wrappers (@ObservedObject, @EnvironmentObject, @Published) and depends on Combine under the hood.
iOS 17 introduced the @Observable macro with granular property-level observation. The app targets iOS 17+.
Decision
Use @Observable for all state management classes. Migrate existing @ObservableObject implementations when touching related code.
Before (ObservableObject):
class AuthenticationManager: ObservableObject {
@Published var isAuthenticated = false
@Published var currentUser: User?
}
struct ContentView: View {
@ObservedObject var authManager: AuthenticationManager
}
After (Observable):
@Observable
class AuthenticationManager {
var isAuthenticated = false
var currentUser: User?
}
struct ContentView: View {
var authManager: AuthenticationManager
}
Use @State for model creation in views, @Bindable instead of @ObservedObject for two-way binding, and @Environment instead of @EnvironmentObject for dependency injection.
Consequences
Views only redraw when properties they actually observe change. Less boilerplate — no @Published annotations, fewer property wrappers. Aligns with Swift 6 concurrency patterns.
No impact on GraphQL integration, Apollo client usage, or testing approaches.