Jan
11/13/2023, 10:33 AMSkieSwiftFlow<FirstLevel<List<SomeItem>>>
but instead we're getting
SkieSwiftFlow<FirstLevel<NSArray>>
Android code:
fun getFlowTwoLevels(): Flow<FirstLevel<List<SomeItem>>>
sealed class FirstLevel<out T> {
data class Success<T>(
val secondLevel: SecondLevel<T>
): FirstLevel<T>()
}
sealed class SecondLevel<out T> {
data class Success<T>(
val result: T,
): SecondLevel<T>()
data class Error(val error: String): SecondLevel<Nothing>()
}
If you'd like to reproduce the bug, please use the repo linked below. It contains Android and iOS demo projects.
https://github.com/JasiekRadzik/KMP_SKIE_NSArray/tree/mainFilip Dolník
11/13/2023, 10:38 AMList<SomeItem>
to NSArray
in generics is an expected behavior / limitation of the Obj-C to Swift interop. You would get the same result if your function returned just FirstLevel<List<SomeItem>>
without the Flow (and even without SKIE).
The problem is that Obj-C generics require the type argument to be a reference type which Swift.Array ([SomeItem]
) is not. Note that the type is not coverted to List<SomeItem>
because that’s a Kotlin only type that doesn’t exist in Obj-C / Swift and instead is translated by the Kotlin compiler to NSArray.Jon Bailey
11/13/2023, 11:04 AMFilip Dolník
11/13/2023, 11:12 AMKotlinList
instead of NSArray
which is actually worse. The Kotlin compiler could in theory export it as a class instead but there are some other problems with this approach. Mainly that Swift does not support covariance for custom generic types which is a big problem for collection types. (Swift collection types like Array
are covariant because they have special support in the Swift compiler which the Kotlin compiler cannot use.)Jacob Ras
11/14/2023, 12:13 PMfun getFlowTwoLevels(): Flow<FirstLevel<SomeItemList>>
class SomeItemList(val items: List<SomeItem>)
Filip Dolník
11/14/2023, 12:16 PMfun getFlowTwoLevels(): Flow<FirstLevel<CustomList<SomeItem>>>
class CustomList<T>(val items: List<T>)
Jacob Ras
11/14/2023, 12:16 PMJan
11/14/2023, 2:00 PM