Hi All, has anyone tried sharing androidx viemodel...
# multiplatform
a
Hi All, has anyone tried sharing androidx viemodel in KMM, how it work with swiftUI ?
it’s working, just adding some glue for iOS and it’s done
r
Hi @Abhishek Agarwal, additionally The Fantasy Premier League sample https://github.com/joreilly/FantasyPremierLeague also provides an example of this with handling the clearing of the ViewModel. I also wrote a blog post which might be helpful https://appmilla.com/latest/getting-started-with-jetpack-viewmodels-and-datastore-in-kotlin-multiplatform/
a
thank you @François @Richard Woollcott for sharing the resource. Also as I am thinking of using it in my production code, just wanted to know if you guys have used this in production code ? if yes, was there any problem especially with swiftui observing the properties just like it works with @Published variable ?
f
You can use it in production, no big issue. just respect the lifecycle of the viewmodel from SwiftUI and be aligned with Android Compose. My Playground has different approach, you can use the SKIE one, it’s working well.
👍 1
a
Hi @François, while doing the POC with the approach that you suggested , I just realised that SKIE all modifiers for swiftui for observing flow are available from ios 15 but our min deployment target is 14 so we can't use that. So what should be the ideal approach here ? Should I just create a separate vm for ios that will use the sharedviewmodel to collect it flow and send data (kind of wrapper)?
f
Oh, I see you can’t use the
.thread
modifier, it’s a bit more tricky in this case. you can look at the previous sample or my example using macro. it’s means, instead of binding your view from the
.task
modifier, you need to do it the old way, from the
.onAppear
From the SKIE documentation .
Copy code
.onAppear {
    Task {
      await viewModel.activate()
    }
}
a
I was actually talking about the SKIE swiftui modifier to observe flow of my shared viewmodel directly from swiftui view. Like collect or Observing()
f
Yes, it’s not compatible with iOS 14, you need to use the old way.
And it’s call DataBinding on MVVM pattern
a
yes , for this case even I have shared viewModel , I have to write another viewmodel for ios that will use the shared vm internally. something like ? or is there any better approach that you can suggest ?
Copy code
@MainActor
class IOSVM: ObservableObject {
  let kmmVM = SharedViewModel()
   
  @Published var state: ViewState = .ideal
   
  func activate() async {
    for await state in kmmVM.mayriLFlow {
       
      switch onEnum(of: state) {
      case .error(_):
        self.state = .ideal
      case .loading(_):
        self.state = .ideal
      case .success(let data):
        self.state = .success(data.data as? MayriState)
      }
    }
  }
   
  func send(action: ViewAction) {
    kmmVM.sendAction(action: action)
  }
}
f
you’re using the KMP ViewModel right? the same as you”re using for Android?
a
yes
f
So, first, you need to manage correctly the lifecycle of the viewmodel and there is some requirement (except the SKIE one)
Adapt the
ViewModelStore
usage as your needs
a
Sorry my bad. Forgot to handle that. This is how my ios vm looks like now
Copy code
@MainActor
class SharedViewModelStoreOwner<VM : ViewModel> : ObservableObject, ViewModelStoreOwner {
  var viewModelStore: ViewModelStore = ViewModelStore()
   
  private let key: String = String(describing: type(of: VM.self))
   
  init(_ viewModel: VM = .init()) {
    viewModelStore.put(key: key, viewModel: viewModel)
  }
   
  var instance: VM {
    get {
      return viewModelStore.get(key: key) as! VM
    }
  }
   
  deinit {
    viewModelStore.clear()
  }
}



//Apprahc 2

enum ViewState {
  case loading
  case ideal
  case success(MayuriState?)
}


@MainActor
class MayuriVM: SharedViewModelStoreOwner<SharedViewModel> {
   
   
  @Published var state: ViewState = .ideal
   
   
   
  func activate() async {
    for await state in instance.mayuriFlow {
       
      switch onEnum(of: state) {
      case .error(_):
        self.state = .ideal
      case .loading(_):
        self.state = .ideal
      case .success(let data):
        self.state = .success(data.data as? MayuriState)
      }
    }
  }
   
  func send(action: ViewAction) {
    instance.sendAction(action: action)
  }
}
f
At least the lifecycle is respected.
Yes, this way is working, kind of boilerplate.
Store directly the value of mayuriFlow inside the SwiftUI ViewModel
Copy code
for await state in instance.mayuriFlow {
    viewState = state
}
Then add the
switch
directly in the SwiftUI View
your
MayuriVM
should be used as a bridge
a
Thank you for the suggestion , will surely do it , It's just POC😅
a
yes, also can I somehow reduce the boilerplate that I have to write , also my team has to make sure to call viewmodel.activate() inside onAppear to make whole thing work
f
even on pure SwiftUI, you need to call a sort of
viewmodel.activate()
, so no big change
a
Actually mostly we just do simple api calls , so just a property with @Published works well , whenever user interact with the view , we send action to vm which update the published property so no something like `viewmodel.activate()`is needed in our case for pure swiftui
f
Ok, I see, but you must trigger the binding of the VM, it’s a part of the glue needed for using a KMP ViewModel.
I’m exploring for months a good way to implement it.
a
Thank you very much for your assistance. I truly appreciate the help you’ve provided. And please let me know if you figured out something.
Till then I will be using this glue to make my sharedVM work in ios
f
My playground is available, I will continue my exploration 😄
Good luck 🙂
🙌 1
Oh, I should add a example without SKIE for SwiftUI and avoid iOS 15 requirement 😄
a
yes, that would definitely help other developers. , I would be more that happy raise a PR for that 😅
Also , though I will not be using SKIE for observing the flow due to their ios 15 requirement, but still SKIE will be useful for sugar coating the objective c function generated from kotlin
f
SKIE is unavoidable tools to use with KMP, made by touchlab, the biggest contributor, you should take a look at the other tools they’re proposing https://touchlab.co/oss.
💯 1
It's just like the current SKIE implementation but with some adaptation without using the
task
modifier
I made on the SKIE forum about that idea.
🎉 1
a
Hey @François , can I dm you ? I have some doubts and need your help to understand it.
f
Yes of course 🙂