1

I'm having trouble trying to understand the hierarchy using SwiftUI's @EnvironmentObject wrapper. I've got a ViewModel that needs to be accessed in multiple screens within the app so I've put this code inside the main app file:

var chartsModel = ChartsViewModel()

Inside the ContentView file generated by Xcode on a new project I have put this inside the ContentView_Previews

ContentView().environmentObject(ChartsViewModel())

Where I'm now getting confused is I have a view 2 levels deep inside ContentView that needs data from the ViewModel.

ContentView()->HomeView()->ChartView()

ChartView is a child of HomeView()

I can get ChartView to display the data when in preview mode by using the following code.

@EnvironmentObject var viewModel: ChartsViewModel

The problem is when previewing HomeView, ContentView or running the app on a device nothing is outputted.

1
  • 1
    You should also put ".environmentObject(ChartsViewModel())" in the content view that is defined in your main app file. You probably do somewhere in your main app file ContentView(), that needs to be changed to ContentView().environmentObject(ChartsViewModel()) Commented Feb 5, 2021 at 21:41

1 Answer 1

0

Inside the ContentView file generated by Xcode on a new project I have put this inside the ContentView_Previews

You should do this not only in preview provider (which is for Preview mode), but in scene creation as well (so it works for runtime), like

@main
struct SwiftUI2App: App {
    var chartsModel = ChartsViewModel()

    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(ChartsViewModel())   // << here !!
        }
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

So to clarify. It has to be passed down the hierarchy through each view until each reaches the child view that needs it. Using ContentView().environmentObject(ChartsViewModel()) then HomeView().environmentObject(ChartsViewModel())?
No, it is needed only in root view to be available through entire hierarchy, but if you want to transfer it in different hierarchy, say sheet, then you need to inject it in that new content explicitly.
Ok, and then I would just access it from any view using the following: @EnvironmentObject var viewModel: ChartsViewModel?
Must I past the environment object from the root view? For example, if I have view A -> B -> C -> D, where A is the root view (e.g. ContentView), and I only want C & D to share an environment object, do I have to pass in environment object in B? From my testing, it seems like I have to pass in inside A

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.