— iOS, SwiftUI, Programming, @Observable, Reactive Programming — 2 min read
iOS 17 introduces the @Observable API, a significant advancement for state management in the SwiftUI framework. This blog post will delve into the essential details of @Observable, providing some insights into its implementation and advantages for iOS developers.
The @Observable API in iOS 17 is part of the Observation framework, a Swift-specific implementation of the observer design pattern. This framework simplifies tracking and responding to changes in data within an app, particularly in SwiftUI applications. The @Observable macro allows developers to mark a class as observable, ensuring that any changes in its properties are noticed and can trigger UI updates accordingly. It's pretty much an evolution of ObservableObject which has been around since iOS 13.0. (After spending a couple of years heavily developing in Flutter it makes me really happy to know there is a good state management solution out of the box with SwiftUI).
To use @Observable, you first need to import the Observation framework. A typical implementation involves declaring a class with the @Observable attribute and defining its properties. For example:
1import SwiftUI2import Observation3
4@Observable5class UserModel {6 var name: String = "Fred"7 // Other stuff8}
Once you've defined an observable object, you can integrate it into your SwiftUI views. SwiftUI views automatically create a dependency on an observable object when a property of the object is read inside the view's body
. When a tracked property changes, SwiftUI updates the view, leading to real-time UI adjustments.
For example:
1struct ContentView: View {2 @Environment(UserModel.self) private var user: UserModel3 4 var body: some View {5 VStack {6 Text("Hello, \(user.name)!")7 Button("Change name") {8 user.name = "Bob"9 }10 }11 .padding()12 }13}14
15@main16struct MyApp: App {17 @State private var userModel = UserModel()18
19 var body: some Scene {20 WindowGroup {21 UserProfileView()22 .environment(userModel)23 }24 }25}
In this example, ContentView
automatically updates whenever user.name
changes, thanks to the @Observable property of UserModel
. When you tap the "Change name" button you'll see that the name automatically changes in the Text view.
As you can also see in the example code above you can now use @State to create your model before injecting it with .environment. You might also have noticed that you no longer use @EnvironmentObject anymore - you need to use @Environment instead.
To use @Observable, developers need to work with iOS 17, macOS 14, and Xcode 15. I think this aspect is kind of disappointing, I wish they had backported it for previous versions of iOS too but this seems to be Apple's approach with any new SwiftUI features or frameworks. In the mean time I did find a library called Perception that has done the work of backporting @Observable. There is a little bit of extra boilerplate but I'm itching to try it out in one of my projects. I'll make sure to write a post about it when I get around to doing so.