Hi! Is it possible to create Skie flows from Swift...
# touchlab-tools
p
Hi! Is it possible to create Skie flows from Swift? My use-case is that I have an interface in KMP that uses
Flow<Int>
as the type for one of the fields, and that interface when translated to Swift uses
SkieSwiftFlow<Int>
. This interface should be implemented by one of my Swift classes. What’s the best/easiest way for the Swift class to create an instance of
SkieSwiftFlow<Int>
?
s
Can you adjust your code to implement this interface in Kotlin, in the
iosMain
directory instead? And then inject some 'plain' swift/objective-x implementation into that?
p
I could, but that would challenge the architecture of the app quite a bit (this is an existing application). The solution so far has been to make a flow factory in
nativeMain
, and call out to those factory functions to create instances of the Skie flows. It’s a bit primitive, but it works. The main downside is that it’s not possible to make it into a generic
fun <T> createFlow(): Flow<T>
, since that translates to
func createFlow(value: Any?) -> SkieSwiftOptionalFlow<Any>
. That optional type is a bit of a hassle to work with, so right now I’m left with writing factory functions for all relevant types I want to create flows for…
f
Hi! Creating SwiftFlows from Swift is relatively complicated but doable - depends on what you need exactly. Because of how they work, SwiftFlows always need a backing KotlinFlow - which is also what determines their behaviour. You can create a KotlinFlow using a regular Kotlin Coroutines function like
flowOf
, cast it to KotlinFlow of the correct type and then use a conversion constructor provided by SKIE to cast it to SwiftFlow . (however, you need to export the whole coroutines in order to do that, so it might be better to write your wrapper to limit the amount of exported declarations) Obviously this doesn’t directly solve the the issue with generics being lost in case where you care about the actual type of the Flow returned from Kotlin, but there are workarounds as well. For example you can “capture” the type using a generic Kotlin class resulting in a syntax like:
FlowFactory<SomeClass>().create()
which would return
SkieSwiftFlow<SomeClass>
without the need for any Swift side conversions. in both cases you can write swift generic functions and call the above code from them to improve the syntax - hiding all that ugly casting.