Ivan Carracedo Asensio
02/03/2024, 7:41 PMKMMViewModelCore/ObservableViewModelPublishers.swift:26: Fatal error: ObservableViewModel has been deallocated
• I add video of the crash
import SwiftUI
import KMMViewModelSwiftUI
import kmpShared
struct AppRootView: View {
@StateViewModel var viewModel = ViewModels.shared.getHomeViewModel()
var body: some View {
NavigationView {
VStack {
NavigationLink {
ContentView2()
} label: {
Text("push to login")
}
}
}
}
}
struct ContentView2: View {
@StateViewModel var viewModel = ViewModels.shared.getOnBoardingViewModel()
var body: some View {
ZStack {
VStack {
Text("Hello Content View 2")
}
}
}
}
Maybe @Rick Clephas have the magic solutionRick Clephas
02/03/2024, 7:48 PM@...ViewModel
property wrappers will automatically create that wrapper for you.
Once the property wrapper is deallocated so is the wrapper.
This can result in the mentioned error when you are reusing the Kotlin VM instances. To solve this (while still being able to reuse the VMs) you should manually keep a reference to this wrapper.
To get/create the wrapper you can use the observableViewModel(for:)
function.Ivan Carracedo Asensio
02/03/2024, 8:51 PMstruct AppRootView: View {
let viewModel = observableViewModel(for: ViewModels.shared.getRouterViewModel())
var body: some View {
NavigationView {
VStack {
NavigationLink {
ContentView2()
} label: {
Text("push to login")
}
}
}
}
}
struct ContentView2: View {
let viewModel = observableViewModel(for: ViewModels.shared.getOnBoardingViewModel())
var body: some View {
ZStack {
VStack {
Text("Hello Content View 2")
}
}
}
}
Rick Clephas
02/03/2024, 9:03 PMAppRootView
will work (assuming it is never destroyed). Though in that case you want to keep the property wrapped view model in ContentView2
.
Note: since you are already reusing the VM you can use ObservedViewModel
instead of StateViewModel
(normally you use the state one to preserve the same VM instance for that specific view).
It might also be worth asking why you are reusing the VMs. Normally when you close a view and reopen it it makes sense to also have a new VM for that newly opened view.Ivan Carracedo Asensio
02/03/2024, 9:38 PMIvan Carracedo Asensio
02/03/2024, 9:45 PMRick Clephas
02/03/2024, 9:45 PM@StateViewModel
is indeed what you are looking for. How does the ViewModels
object in Kotlin look like?Ivan Carracedo Asensio
02/03/2024, 9:49 PMopen class SignUpViewModel() :
KMMViewModel(), KoinComponent {
}
then in the koin ios part I do:
single *{* SignUpViewModel() *}*
and then the helper:
object ViewModels : KoinComponent {
fun getSignUpViewModel() = getKoin().get<SignUpViewModel>()
}
Ivan Carracedo Asensio
02/03/2024, 9:49 PMIvan Carracedo Asensio
02/03/2024, 9:50 PMopen class SignUpViewModel(val routeNavigator: RouteNavigator) : KMMViewModel(), RouteNavigator by routeNavigator, KoinComponent {
Ivan Carracedo Asensio
02/03/2024, 9:50 PMIvan Carracedo Asensio
02/03/2024, 9:50 PMRick Clephas
02/03/2024, 9:52 PMsingle
call in the koin module. Try and use factory
instead.Rick Clephas
02/03/2024, 9:53 PMfactory
your original SwiftUI code should work as expectedIvan Carracedo Asensio
02/03/2024, 9:53 PMIvan Carracedo Asensio
02/03/2024, 9:53 PMIvan Carracedo Asensio
02/03/2024, 9:53 PMIvan Carracedo Asensio
02/03/2024, 9:54 PMRick Clephas
02/03/2024, 9:55 PMsingle
function. The difference being that with factory
koin will create a new instance instead of returning the same singleton.Ivan Carracedo Asensio
02/03/2024, 10:20 PMIvan Carracedo Asensio
02/03/2024, 10:21 PMRick Clephas
02/03/2024, 10:24 PM