New Observation in SwiftUI

Ahmed Adam
3 min readJul 4, 2023

--

SwiftUI new data flow in iOS 17.

In the latest version of SwiftUI (iOS 17), there is an exciting new feature called the @observable macro, which offers a cleaner and more efficient way to handle UI updates. Let's explore how it works by converting an existing code example.

import SwiftUI

class Car: ObservableObject {
@Published var name: String
@Published var speed: Int

init(name: String, speed: Int) {
self.name = name
self.speed = speed
}
}


struct ContentView: View {
@StateObject var car = Car(name: "BMW", speed: 100)

var body: some View {
VStack {
Text("\(car.name)")
.bold()
.font(.title)
Text(" \(car.speed)")
.font(.title2)
Button{
car.speed += 1
} label: {
Text("Add")
}
.buttonStyle(.borderedProminent)
.padding(.top)
}
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

Currently, when we want to update our UI based on changes in our data model, we conform to the ObservableObject protocol. We mark any property we want to observe with @Published, which tells SwiftUI to update the UI whenever that property changes. In our example, we have a Car data model, and whenever the speed property changes, the UI updates because it is marked with @Published. Additionally, we use @StateObject or @ObservedObject wrappers in our views to indicate that we want to observe changes to the Car object.

To demonstrate the new way of updating the UI, we introduce the @observable macro. We import the Observation module and replace the ObservableObject conformance with the @observable macro. This simple change eliminates the need for the @Published annotations on individual properties. Instead, all properties within the @observable class are automatically observed.

import SwiftUI
import Observation

@Observable class Car{
var name: String = ""
var speed: Int = 100

init(name: String, speed: Int) {
self.name = name
self.speed = speed
}
}


struct ContentView: View {
var car = Car(name: "BMW", speed: 100)

var body: some View {
VStack {
Text("\(car.name)")
.bold()
.font(.title)
Text(" \(car.speed)")
.font(.title2)
Button{
car.speed += 1
} label: {
Text("Add")
}
.buttonStyle(.borderedProminent)
.padding(.top)
}
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

In the updated code, our data model is a Car class with properties like name and speed. We mark the class with @observable and provide initial values for its properties to satisfy the requirements of the new macro. The @Published annotations are no longer needed, as all properties are now observed by default.

In our SwiftUI view, instead of using @StateObject or @ObservedObject, we declare a @var property called car of type Car. This property is automatically observed, simplifying the code and eliminating the need to choose between @StateObject and @ObservedObject.

The @observable macro offers more than just cleaner syntax. Under the hood, SwiftUI tracks the views that access properties of an observable class, enabling more efficient UI updates. By eliminating unnecessary UI updates, SwiftUI can deliver better performance. This tracking allows SwiftUI to be more precise and efficient in updating only the necessary parts of the UI.

One additional benefit of using macros, such as @observable, is that they abstract away repetitive and boilerplate code. While the inner workings of the macro may seem like magic, Xcode 15 beta 2 introduces a feature where you can expand the macro and see the generated code. This visibility into the generated code can help debug any issues and understand the underlying mechanics, to check it right click on @observable then hit “Expand Macro”.

In summary, adopting the @observable macro in SwiftUI brings cleaner syntax and improved performance to UI updates. By leveraging the macro, SwiftUI tracks views accessing properties of observable objects, reducing unnecessary UI updates and resulting in better performance. This update is a significant improvement for SwiftUI developers.

--

--

Ahmed Adam
Ahmed Adam

Written by Ahmed Adam

Senior iOS Engineer | Swift | SwiftUI | Objective-C | Agile | Scrum | Mobile Development |

Responses (1)