@Observable init() called multiple times by @State, different behavior to @StateObject

What I do is wrap the Observable in an ObservableObject to hold the single intended instance

@Observable class Foo { 
    var value = 0 
}

class FooHolder: ObservableObject {
    let foo = Foo()
}

struct MyView: View {
    @StateObject var holder = FooHolder()
    var body: some View {
        Text("\(holder.foo.value)")
    }
}

The name isn’t as clean but I prefer that over pointless instantiation. However it gets worse if you want a Binding where my solution is to split it between 2 views, one to hold the instance the other for Bindable.

struct MyView: View {
    @StateObject var holder = FooHolder()
    var body: some View {
        MyViewReal(foo: holder.foo)
    }
}

struct MyViewReal: View {
    @Bindable var foo: Foo
    var body: some View {
        Stepper("", value: $foo.value)
    }
}

And of course you can make a generic holder class but a generic property name makes it unsatisfying to work with

class ObservableHolder<T: Observable>: ObservableObject {
    let object: T
    init(_ obj: T) { object = obj }
}
1 Like