We are building a multiplatform shared module whic...
# touchlab-tools
a
We are building a multiplatform shared module which is providing ViewModels, but not Views. How do I best provide a Coroutine scope and all the lifecycle stuff on iOS? Ideally I want to use the KMP-ViewModel directly as state and for callbacks. I need to pass some arguments into the constructor of the ViewModel.
For now: I've removed the compose ViewModel again. Instead I've built a new view model base class with an explicit '.clear()' method and let the clients handle the lifecycle directly. In case of iOS that method can be called in a
deinit {}
block
f
Take a look here for the lifecycle https://github.com/frankois944/kmp-mvvm-exploration
You can use the same implementation for the KMP or the CMP viewmodel
d
I'm curious about this because I've generally been building my KMP projects without sharing VMs but would like to try sharing them - what is your exact use case for the clear() function? Wouldn't the viewmodel automatically be destroyed when your ViewController/SwiftUI is destroyed and stops referencing it? Excuse my ignorance if I'm missing something obvious
f
Your KMP ViewModel must have the same behavior on iOS(SwiftUI/UIKIt)/Android(Compose)/CMP. The method
onCleared
is important as it’s the only way to know/do the ViewsModel has been destroyed correctly. > - what is your exact use case for the clear() function? We can’t call directly the onCleared, as this is an internal method, and the only way is using the ViewModelStore like Compose does. The ViewModelStore
clear()
function calls the ViewModel
onCleared
method and do some cleaning stuff (like cancellation). > Wouldn’t the viewmodel automatically be destroyed when your ViewController/SwiftUI is destroyed and stops referencing it? Yes, but the
viewModelScope
won’t be canceled correctly, and other stuff linked behind the KMP ViewModel.
The SwiftUI ViewModel is destroyed on the
deinit
event, NOT
onDisappear
event, the KMP ViewModel should do the same on SwiftUI/UIKIt.
a
@François Thank you very much!
d
Right so if I understand correctly, this is really only a problem for pure SwiftUI apps because: • CMP/KMP/Android works out of the box because androidx viewmodel is KMP • If you use UIKit/hostingVC (e.g. as wrapper just to avoid doing navigation in SwiftUI) you can manage your VM lifecycle without problems (i.e. via coordinator pattern) 🤔
f
On Compose the ViewModel lifecycle is managed by your navigation framework which use the
ViewModelStore
, there is no such thing on SwiftUI.
The SwiftUI ViewModel use StateObject + ObservableObject to manage the lifecycle of a ViewModel
d
Yep so that agrees with my 2 bullet points above I think?
f
yes, that’s it
thank you color 1
I guess, you need to understand how a SwiftUI ViewModel is managed and how to apply the same rules to the KMP ViewModel
👍 1
My current Github use the old way < iOS 17. But currently, the SwiftUI ViewModel is simplier (with macro) : https://www.hackingwithswift.com/books/ios-swiftui/introducing-mvvm-into-your-swiftui-project
d
Right but even that article doesn't go into enough detail to be useful enough on it's own - it doesn't mention when exactly
Copy code
@State private var viewModel = ViewModel()
would be destroyed/cleared and also doesn't cover any async work happening in the VM. Granted that could be a bit easier with iOS's Task API but 🤷
Also, look at my repository and different possible usage I found of the KMP ViewModel