Share ViewModel in NavigationStack views only

I have a NavigationStack with three forms, each with a couple of screens. I need to share a form’s ViewModel only across its screens without having to create an instance globally (inside ContentView). Currently each ViewModel is always created, regardless of whether it is used or not.

I have tried placing each form inside its own NavigationStack, but nested NavigationStack does not work for me.

If you have gotten nested NavigationStack working or have other alternatives, please share.

struct ContentView: View {

    @StateObject private var pathStore = PathStore()

    @StateObject var formOneVM = FormOneViewModel()
    @StateObject var formTwoVM = FormTwoViewModel()

    var body: some View {

        NavigationStack(path: $pathStore.path) {

            HomeView()
            .navigationDestination(FormOneRoutes.self){ route in
                switch route{
                    case .screenOne:
                        FormOneScreenOne()
                    case .screenTwo:
                        FormOneScreenTwo()
            }
            .navigationDestination(FormTwoRoutes.self){ route in
                switch route{
                    case .screenOne:
                        FormTwoScreenOne()
                    case .screenTwo:
                        FormTwoScreenTwo()
        }
    }
    .environmentObject(formOneVM)
    .environmentObject(formTwoVM)
}

To share a form’s ViewModel only across its screens without creating a global instance, you can use the @EnvironmentObject property wrapper to inject the ViewModel into the NavigationView.

First, create an ObservableObject subclass for each ViewModel:

class FormOneViewModel: ObservableObject {
    // Your implementation
}

class FormTwoViewModel: ObservableObject {
    // Your implementation
}

Then, modify your ContentView as follows:

struct ContentView: View {

    @StateObject private var pathStore = PathStore()

    // Create instances of the ViewModels
    @StateObject var formOneVM = FormOneViewModel()
    @StateObject var formTwoVM = FormTwoViewModel()

    var body: some View {
        NavigationView {
            // Inject the ViewModels using the @EnvironmentObject property wrapper
            HomeView()
                .navigationDestination(FormOneRoutes.self) { route in
                    switch route {
                    case .screenOne:
                        FormOneScreenOne()
                    case .screenTwo:
                        FormOneScreenTwo()
                    }
                }
                .navigationDestination(FormTwoRoutes.self) { route in
                    switch route {
                    case .screenOne:
                        FormTwoScreenOne()
                    case .screenTwo:
                        FormTwoScreenTwo()
                    }
                }
                .environmentObject(formOneVM) // Inject the FormOneViewModel
                .environmentObject(formTwoVM) // Inject the FormTwoViewModel
        }
    }
}

Now, the FormOneViewModel and FormTwoViewModel will be shared only across their respective screens, and an instance will not be created globally inside ContentView.