Andrew Reed
09/27/2023, 12:46 PM@Compose
fun coolView(viewModel: CoolViewModel) {
val coolValue = viewModel.fooFlow.collectAsState()
....
Whereas in swift, really i would like to be able to do something like this:
struct CoolView: View {
let viewModel: CoolViewModel
@State var coolValue = viewModel.fooFlow.collectAsState()
....
I was just wondering if anybody came up with a smart extension for this?
extension SkieSwiftFlow {
func collectValue(callback: @escaping (_ value: T) -> Void) {
Task.init {
for await awaitedValue in self {
callback(awaitedValue)
}
}
}
}
Then you could. do something like:
struct CoolView: View {
let viewModel: CoolViewModel
@State var coolValue: Bool = false
init (viewModel: CoolViewModel) {
self.viewModel = viewModel
viewModel.fooFlow.collectValue {
self.coolValue = $0
}
}
....
Sorry for the essay, but how else do people collect values from the SKIE flow? i saw the mainActor stuff, but it would be noisy for lots of values, unless you created your own wrapper viewmodel and did it there but im a beleiver that the Kotlin generated view model should be useable from native without a wrapper.streetsofboston
09/27/2023, 1:14 PMObservable
class (like a ViewModel) that holds Published
vars describing your UI-state. A wrapper would be needed, regardless.
It'd be nice if Skie could make such a wrapper as well (backed by a KMP ViewModel class) 😁
Right now, I'm using async for-loops in Swift for collecting the Skie Flows.Andrew Reed
09/27/2023, 2:48 PMstreetsofboston
09/27/2023, 3:02 PMlaunchIn
or some sort of method...Andrew Reed
09/27/2023, 5:05 PMrusshwolf
09/27/2023, 5:06 PMfor async
loops, though the project I'm currently focused on isn't sharing viewmodels so this all happens a little lower down.
Beyond SKIE, I think there's a gap even in the pure Swift ecosystem around making it easier to bind the output of an AsyncSequence to SwiftUI, but I also haven't caught up with the latest versions of Swift/SwiftUI to know what's been added around this.Andrew Reed
09/27/2023, 5:07 PMrusshwolf
09/27/2023, 5:10 PMtask
modifier on the swiftui view. You could pull that out into an extension but the generics can get a bit messy when you need it to interact with an arbitrary viewmodelAndrew Reed
09/27/2023, 5:19 PMrusshwolf
09/27/2023, 5:29 PMkpgalligan
09/27/2023, 8:09 PMcollectAsState()
and something similar for SwiftUI on top of SKIE (or separate, depending) is big on my mind now. One of the primary SKIE devs built this https://github.com/Brightify/Hyperdrive, which (in part) does this kind of thing, but using Objc classes. My thinking is really just that StateFlow could be exposed as form form of "state", and consumed that way, rather than the loop. That might be enough, but my SwiftUI architectural understanding is a bit underdeveloped to think through the range of scenarios that would need to be addressed, and how whatever is accessing that state is created, it's lifecycle, etc. I really don't want to prescribe extra ceremony around any sort of lifecycle that would be odd from a Swift perspective, though. anyway, we can generate Swift now, and link it back into the framework. Knowing that, what do you think this should look like?Andrew Reed
09/28/2023, 10:10 AMJeff Lockhart
09/28/2023, 3:09 PMin an ideal world, i would foresee, an KMP viewmodel object type, for Android this would use the ViewModel type that has all the lifecycles attached to it.
For iOS i guess would be an observableobject
Sounds like what @Rick Clephas's https://github.com/rickclephas/KMM-ViewModel does.
kpgalligan
09/28/2023, 4:35 PMStateFlow
to published state in SwiftUI. However, There's a long-standing debate about getting away from ViewModel
. I'm not 100% set on doing that, but I do think there's some value in thinking through where the shared code split exists, and how that gets exposed on either side. I guess my gut feeling is if you're going to create some kind of "view model", you could have both platforms derive from the same object. Or, you could have something different for iOS that is unrelated. You aren't required to derive from the same base and have a somewhat shared lifecycle. As for generating something on the Swift side, I'm more interested in seeing complex examples of how you'd architect the data if there wasn't any Kotlin in the mix. How are you managing async contexts and lifecycles, etc. We started with various flavors of shared ViewModel
, capital 'V', and trying to match the lifecycle of the VM with whatever was happening on Swift, but it very much feels like we're pushing an Android abstraction onto SwiftUI. Worse, it's an abstraction that is very much up for debate, even on Android. Yada yada. I want to understand how this would ideally look from Swift if there was no Android-isms in the mix, then work back from there. But, the dog got me up at 5am because he doesn't care about my feelings, and I just did a live stream, so now is probably not the best time to debate architecture :)