Closed ghost closed 10 months ago
I believe this is to be expected and also the case for pure Swift ObservableObject
s, right?
It happens when I'm using environment variable, but not when I pass the KMM View Model using DI with constructors of the View. So, in the root view, I would create instance of view model without using @StateObject or @StateViewModel, and then in child view, I would have @StateViewModel for that view model which will be initialized inside init where I would pass the regular view model:
So how are you creating and storing the viewmodel when using @EnvironmentViewModel
?
It sounds like some higher view is also observing the viewmodel, resulting in the calls to the init
.
Inside of the root App
module I have:
@StateViewModel var homeViewModel: HomeViewModel = ViewModelsHelper().homeViewModel
and then:
var body: some Scene { WindowGroup { HomeScreenView() .environmentViewModel(homeViewModel) } }
That explains the calls to the init
. Since you are observing the viewmodel with StateViewModel
in App
the body
is being recreated when a state change happens in your viewmodel. Removing the StateViewModel
property wrapper should fix that.
So then, how do I use .environmentViewModel
?
The following should be enough to use environmentViewModel
:
struct MyApp: App {
var homeViewModel: HomeViewModel = ViewModelsHelper().homeViewModel
var body: some Scene {
WindowGroup {
HomeScreenView().environmentViewModel(homeViewModel)
}
}
}
There's an issue when for example in shared part:
init { viewModelScope.coroutineScope.launch { while (true) { delay(2000) _homeUiState.update { it.copy(error = if (it.error == null) "error" else null) } } } }
When in SwiftUI using this view model as: @EnvironmentViewModel private var homeViewModel: HomeViewModel
and if you implement in SwiftUI screen:
init() { print("code 1 - init") }
.onChange(of: homeViewModel.homeUiState.error) { error in if error != nil { showAlert = true } else { showAlert = false } }
The screen will always be reinitialized. You will always get code 1 - init after state change.