2023 SwiftUI & UI Frameworks
WWDC23 · 13 min · SwiftUI & UI Frameworks
Discover Observation in SwiftUI
Simplify your SwiftUI data models with Observation. We’ll share how the Observable macro can help you simplify models and improve your app’s performance. Get to know Observation, learn the fundamentals of the macro, and find out how to migrate from ObservableObject to Observable.
Watch at developer.apple.com ↗Chapters
Code shown on screen · 8 snippets
Using @Observable
class FoodTruckModel {
var orders: [Order] = []
var donuts = Donut.all
} SwiftUI property tracking
class FoodTruckModel {
var orders: [Order] = []
var donuts = Donut.all
}
struct DonutMenu: View {
let model: FoodTruckModel
var body: some View {
List {
Section("Donuts") {
ForEach(model.donuts) { donut in
Text(donut.name)
}
Button("Add new donut") {
model.addDonut()
}
}
}
}
} SwiftUI computed property tracking
class FoodTruckModel {
var orders: [Order] = []
var donuts = Donut.all
var orderCount: Int { orders.count }
}
struct DonutMenu: View {
let model: FoodTruckModel
var body: some View {
List {
Section("Donuts") {
ForEach(model.donuts) { donut in
Text(donut.name)
}
Button("Add new donut") {
model.addDonut()
}
}
Section("Orders") {
LabeledContent("Count", value: "\(model.orderCount)")
}
}
}
} Using @State
struct DonutListView: View {
var donutList: DonutList
private var donutToAdd: Donut?
var body: some View {
List(donutList.donuts) { DonutView(donut: $0) }
Button("Add Donut") { donutToAdd = Donut() }
.sheet(item: $donutToAdd) {
TextField("Name", text: $donutToAdd.name)
Button("Save") {
donutList.donuts.append(donutToAdd)
donutToAdd = nil
}
Button("Cancel") { donutToAdd = nil }
}
}
} Using @Environment
class Account {
var userName: String?
}
struct FoodTruckMenuView : View {
(Account.self) var account
var body: some View {
if let name = account.userName {
HStack { Text(name); Button("Log out") { account.logOut() } }
} else {
Button("Login") { account.showLogin() }
}
}
} Using @Bindable
class Donut {
var name: String
}
struct DonutView: View {
var donut: Donut
var body: some View {
TextField("Name", text: $donut.name)
}
} Storing @Observable types in Array
class Donut {
var name: String
}
struct DonutList: View {
var donuts: [Donut]
var body: some View {
List(donuts) { donut in
HStack {
Text(donut.name)
Spacer()
Button("Randomize") {
donut.name = randomName()
}
}
}
}
} Manual Observation
class Donut {
var name: String {
get {
access(keyPath: \.name)
return someNonObservableLocation.name
}
set {
withMutation(keyPath: \.name) {
someNonObservableLocation.name = newValue
}
}
}
} Related sessions
-
34 min -
19 min -
22 min -
34 min -
40 min -
9 min -
11 min -
9 min -
16 min