1

I have code like this:

struct MenuView : View {

    @Environment(\.verticalSizeClass) var sizeClass
    @EnvironmentObject var model : MenuModel

    @ObservedObject var items = MenuItems()

    var body: some View { 

    }

}

And I consider why ObservableObject is not keeping it state (there is no one instance of this object) but rather it is recreated (init() method is called) on each View redrawing while some other state changes. I think it is once per object.

But tapping the button causes View to be recreated and also this ObservedObject to be recreated. Should I create it not via property initialization but rather in parent and pass it to constructor?

How to correctly pass @ObservedObject to child view? I consider passing it to @Bindable property but it doesn't work.

I am changing via Button model.isMenuOpen @Published property

1
  • 1
    Yes, you do need to pass it into the intializer in order for it to be retained when the struct is being reinitialized. Commented Nov 25, 2019 at 22:18

1 Answer 1

2

There is some "magic" by SwiftUI in restoring the state (be it @State or @ObservedObject) of a view. Those states are managed by SwiftUI, and they are restored before body is called.

Your child view can have an initialization, but note it has to be like this:

init(foo: Foo) {
    self._foo = ObservedObject(initialValue: foo)
}

You you might also want your view to extend Equatable, to help in the diff-ing.

I wrote more on the weird things about state here: https://samwize.com/2020/04/30/a-few-things-about-state/

Sign up to request clarification or add additional context in comments.

2 Comments

What is the difference between self._foo = ObservedObject(initialValue: foo) and self.foo = foo ?
It is peculiar to only init. You can try with a @ObservedObject var foo = Foo(1) property, and see the bug with self.foo = foo.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.