Consider the following code:
class Model: ObservableObject {
@Published var property1: Int = 0
@Published var property2: Int = 0
}
struct ObjectBindingTest: View {
@StateObject private var model = Model()
var body: some View {
print("——— top")
return VStack(spacing: 30) {
SomeSimpleComponent(property: $model.property1)
SomeSimpleComponent2(property: $model.property2)
}
.padding(50)
}
}
struct SomeSimpleComponent: View {
@Binding var property: Int
var body: some View {
print("component 1")
return HStack {
Text("\(property)")
Button("Increment", action: { property += 1 })
}
}
}
struct SomeSimpleComponent2: View {
@Binding var property: Int
var body: some View {
print("component 2")
return HStack {
Text("\(property)")
Button("Increment", action: { property += 1 })
}
}
}
Whenever you press on one of the buttons, you will see in console:
——— top
component 1
component 2
Meaning that all body blocks get evaluated.
I would expect that only the corresponding row gets updated: if I press the first button and therefore update property1
, the second row shouldn't have to re-evaluate its body because it's only dependent on property2
.
This is causing big performance issues in my app. I have a page to edit an object with many properties. I use an ObservableObject
with many @Published
properties. Every time a property changes (for instance while typing in a field), all the controls in the page get updated, which causes lags and freezes. The performance issues mostly happen in iOS 14; I'm not sure whether they're not happening in iOS 15 or if it's just that the device has more computing power.
How to prevent unnecessary updates coming from ObservableObject
, and only update the views that actually watch the updated property?