Change NavigationStack-path from ViewModel?

254 views Asked by At

I'm trying to implement the MVVM-architecture in my little app and I am confused about how to update the path of my NavigationStack from the ViewModel. My path is a @Published property and gets inserted via an @EnvironmentObject into my View. Via a button I am doing an API-call with the corresponding function being located in my ViewModel. If the API-call is successfull, I want to change the path of my NavigationStack. But I can't access the @Published property inside the ViewModel! I could use a completion handler but that is not clean MVVM, right?

Model:

enum pathCases:  Hashable {
    case Home, Settings
}

class Navigation: ObservableObject {
    @Published var path: [pathCases] = []
}

View:

//...
@EnvironmentObject var navigation: Navigation
//...
NavigationStack(path: $navigation.path) {
   //...
   Button("Make API-Call") {
       myApiFunction()
   }
   //...
}

ViewModel:

@MainActor final class ViewModel: ObservableObject {
    func myApiFunction() {
       //change the array navigation.path - how?
    }
}
1

There are 1 answers

0
pjp288 On

You can have a @Published variable in your viewModel which your View listens to. And you can use the .onChange observer to append your path into the Navigation environmentObject

View:

//...
@EnvironmentObject var navigation: Navigation
//...
NavigationStack(path: $navigation.path) {
   //...
   Button("Make API-Call") {
       myApiFunction()
   }
   //...
}.onChange(of: viewModel.resultOfApi) { resultOfApi in
        if resultOfApi {
            // append to navigation.path here
        }
    }

ViewModel

@MainActor final class ViewModel: ObservableObject {
    @Published resultOfApi = false // for example
    func myApiFunction() {
       resultOfApi = true
    }
}

It is important to understand that the new APIs are "data-driven" so your changes should modify the state of some data container (which is your ViewModel here, and the View simply reacts to it based on the state of the data)