I have a simple Resource Class defined in my shared module - I usually use it as data types for flow...
u
I have a simple Resource Class defined in my shared module - I usually use it as data types for flows returned from my repositories:
Copy code
sealed class Resource<out T : Any>(open val data: T? = null) {
    data class Success<out T : Any>(override val data: T) : Resource<T>()
    class Failed<out T : Any>(val msg: String, val cause: Throwable? = null, data: T? = null) : Resource<T>(data)
    class Loading<out T : Any>(data: T? = null) : Resource<T>(data)
}
I also have a mapper function with allows mapping the data type to something else:
Copy code
fun <T : Any, R : Any> Resource<T>.map(mapper: (T) -> R): Resource<R> = ...
This works great on the Kotlin end of things. But I’m loosing all generic information on the Swift end in the mapper function. It seems to just be converted to
(Any) -> Any
which means I need to constantly cast to get what I want which makes the code look really ugly. I read through the official docs and understand, that this is expected. But is there a better way to handle generic and/or generic resources to make them more Swift compatible?
s
u
@Shubham Singh interesting, will check it out, thanks!
b
Or alternatively put the generic on a class (method object) to avoid losing the type info.
u
@bnvinay92 I’m not super proficient with Swift, how would that look like?
@Shubham Singh I checked out kswift - impressive! But I’m not sure whether it really solves my problem. Am I supposed to define an additional special version of the Flow<Resource<SomeType>> returning repository function which returns Flow<ResourceKs<SomeType>> and use that in Swift while using the original function in Kotlin/Android? -> doesn’t work as ResourceKs only exists on the Swift end. 🤔
b
I meant from the kotlin side of things.
class Mapper<R>(mapper: (MyClass) -> R)
with
fun map(myClass: MyClass): R
If you want to chain mappers this won't be great but the idea is that generics on classes are preserved but function generics become
Any
u
oh, got you - yeah, that would indeed lead to quite a bit of ceremony when attempting to chain (which exactly is one of the use cases for me unfortunately).
b
If you want to chain mappers just map once using kotlin and then convert to a swift type and use whatever is idiomatic in swift
u
yeah, that would work, and I’ll probably do just that if I don’t find a better solution. Guess I should timebox now. 😅
@Shubham Singh I think I now understand how it’s supposed to work: I spit out Flow<Resource<SomeType>> in my shared repository and then map to ResourceKs<SomeType> by using generated constructor and then use ResourceKs going forward. That seems to do the trick, however the mapping extension function mentioned in the first post isn’t generated for ResourceKs as well. Will try now to move the extension function into the sealed class to be a regular instance function.
Alright, seems the extension function thingy is a known issue: https://github.com/icerockdev/moko-kswift/issues/30
Weird, making the function an instance function of Resource also doesn’t seem to cause it to be generated in ResourceKs. 🤔 Any ideas?
Just to sum up what I ended up with: I’m not using kswift. Instead I’m using [Resultat](https://github.com/nicolashaan/resultat) (which is a fork of the built-in Kotlin Result) in Kotlin/native and manually map it to Swift’s Result on the receiving end. Works like a charm.