S.Kr
S.Kr

Reputation: 41

@Observable Macro: Will not marking properties with @ObservationIgnored cause any issues?

I'm migrating old ObservableObjects to the new Observation method with @Observable macro. What happens if I don't mark the previously unpublished properties with @ObservationIgnored?

  1. Would there be any meaningful performance/power penalties? Or any other complications like retaining references?
  2. What if there is no observer objects/views observing that property? Would there be any difference in performance between annotating the property with @ObservationIgnored and not annotating at all?

Example:

original class:

class Class1: ObservableObject {
    @Published var a: Int = 1
    var b: Int = 2
}

new class:

@Observable class Class2 {
    var a: Int = 1
    var b: Int = 2 // Do I absolutely need to use @ObservationIgnored here?
}

Thank you!

Upvotes: 0

Views: 417

Answers (1)

Sweeper
Sweeper

Reputation: 273540

Removing @ObservationIgnored from an @Observable class is roughly similar to adding @Published to an ObservableObject. It can be a breaking change, in the sense that it might change existing behaviour.

A simple but contrived example is:

@Observable
class Foo {
    var x = 0
    @ObservationIgnored
    var y = 0
}

struct ContentView: View {
    @State var foo = Foo()
    var body: some View {
        VStack {
            Text(foo.x, format: .number)
            Text(foo.y, format: .number)
            Button("Change X") {
                foo.x += 1
            }
            Button("Change Y") {
                foo.y += 1
            }
        }
    }
}

Here, tapping "Change Y" will never change the second Text. It is only after you tap "Change X", does the second Text update to reflect the current value of foo.y.

Do note that this doesn't mean foo.y += 1 doesn't change the value of foo.y. foo.y is still set correctly. It's just the view's body is not called to reflect the change.

Removing @ObservationIgnored will change the behaviour. Tapping "Change Y" will now always update the view.

If no view has a dependency on the "ignored" property (this means you are not calling the getter/setter of the property in body), then there will be no change in the behaviour.

Performance-wise, there will potentially be more view updates as explained by the aforementioned example, but assuming no view has a dependency on the ignored property, you will just get a little extra overhead in the getter/setter of the ignored property, because the macro-generated getter/setter records property accesses into the observation registrar. I don't think this will be a noticeable difference.

Upvotes: 1

Related Questions