Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiplatform support #91

Closed
emilbutiri opened this issue May 31, 2024 · 7 comments · Fixed by #123
Closed

Multiplatform support #91

emilbutiri opened this issue May 31, 2024 · 7 comments · Fixed by #123
Labels
enhancement New feature or request

Comments

@emilbutiri
Copy link

emilbutiri commented May 31, 2024

Hi! Now that the Jetpack lifecycle and view model libraries have multiplatform support, I was wondering if this library could be made multiplatform compatible. In my case, I'm thinking of iOS, and being able to scope a ViewModel to a SwiftUI View.
I know of two solutions so far:

  1. KMP-ObservableViewModel solution where using the @StateViewModel annotation will take care of the lifecycle and ensure the view model is cleared when the View is destroyed

  2. This solution, that I'm currently using myself, and seems to work fine, though there's a bit of boilerplate involved (maybe because I don't know any better):

In the iOS app, create a ViewModelOwner class that implements the ViewModelOwner interface. This requires the shared module to export the Jetpack viewmodel library.

// ViewModelStoreOwner.swift

import shared 

class ViewModelStoreOwner: shared.ViewModelStoreOwner {
    internal let viewModelStore = ViewModelStore()
    
    fileprivate func put<VM: ViewModel>(_ vm: VM) {
        viewModelStore.put(key: VM.self.description(), viewModel: vm)
    }
    
    // This is called when the View containing this object is destroyed
    deinit {
        viewModelStore.clear()
    }
}

// A helper function to create a ViewModel with an owner
func viewModel<VM: ViewModel>(owner: ViewModelStoreOwner, _ factory: () -> VM) -> VM {
    let vm = factory()
    owner.put(vm)
    return vm
}

Then in a View implementation:

// SomeView.swift

import SwiftUI

struct SomeView: View {
    private let owner = ViewModelStoreOwner()
    private let vm: SomeViewModel

    init() {
        vm = viewModel(owner: owner) {
            SomeViewModel()
        }
    }

    var body: some View {
        // etc
    }
}

I'm using the second method because I don't need all the other stuff KMP-ObservableViewModel offers - I prefer to use SKIE to handle Flows.

But I started wondering if it wouldn't be possible to make viewModelScoped() work inside a SwiftUI View.

Best regards,
/Emil

@sebaslogen sebaslogen added the enhancement New feature or request label Jun 4, 2024
@sebaslogen
Copy link
Owner

Hi Emil, thanks for the detailed description!

I'm also a user of the KMP-ObservableViewModel lib (when it was called KMMViewModel 😅) in my pet project and indeed the @StateViewModel annotation works like a charm.

As for your second solution, that's exactly how KMP-ObservableViewModel is solving the problem in SwiftUI, although the order is slightly different, in there they register the diInit when the observable is created and the VM Store is created only at the last minute (just to call the protected clear method).

Now for your request, I'm thinking about it but I'm still in the early exploration phase, especially since Google introduced KMP support for Android VIewModels).
The thing is that SwiftUI Views have a much more simple lifecycle than Compose on Android, so 90% of the book-keeping that resaca does for all the Android/Compose edge cases is not needed in SwiftUI. So if we strip that, it will end up with basically the same concise code of your solution above (or from KMP-ObservableViewModel), which is definitely good 😃

Next step after testing resaca with the new KMP ViewModel: decide if resaca will support SwiftUI and I'll update this issue with the outcome.

@sebaslogen
Copy link
Owner

I've just found this other implementation following the same options discussed in this thread, the more alternatives the better for reference
joreilly/FantasyPremierLeague@c637670

Original reference from this tweet https://x.com/joreilly/status/1795528038781710465

@enoler
Copy link

enoler commented Jul 29, 2024

I am really interested in KMM support. I am using the latest androidx.lifecycle viewmodel, and sadly, I can not use this library because I am using compose multiplatform and I share the UI between both iOS and android versions.

Is there any plan to add support for it in a near future?

Thanks in advance

@sebaslogen
Copy link
Owner

@enoler Yes, the support for Compose Multiplatform is actually in progress, I made some initial feasibility designs and it looks quite simpel for iOS so I´ll start the implementation this week.

By the way, Compose multiplatform is quite different from the SwiftUI support discussed above in this ticket. Since resaca is a library for Compose, the integration without Compose in a SwiftUI project is simpler and different than all the work that resaca does, so it doesn't really fit in this library. I'm still deciding if it's better to leave SwiftUI as a documentation guide or for another project/library.

@enoler
Copy link

enoler commented Jul 30, 2024

@enoler Yes, the support for Compose Multiplatform is actually in progress, I made some initial feasibility designs and it looks quite simpel for iOS so I´ll start the implementation this week.

By the way, Compose multiplatform is quite different from the SwiftUI support discussed above in this ticket. Since resaca is a library for Compose, the integration without Compose in a SwiftUI project is simpler and different than all the work that resaca does, so it doesn't really fit in this library. I'm still deciding if it's better to leave SwiftUI as a documentation guide or for another project/library.

Happy to read that, in my case I am not using viewmodels on the swift UI, I am handling everything inside compose, so I just import the main composable on swift and the rest it's doing the magic under the hood inside compose.

@sebaslogen
Copy link
Owner

Work for Compose Multiplatform support is tracked on this feature branch #123

@sebaslogen
Copy link
Owner

Compose multiplatform support has been released 🎉

See 4.0.1 (and 4.0.0) https://github.com/sebaslogen/resaca/releases

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants