https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
p

Pavel Lahoda

12/06/2023, 9:18 AM
Is there a way to pass a type as an function argument in KMM? I would like to have something as
Copy code
fun foo(classType: KType)
which maps on iOS to KotlinType. This is not mentioned in https://kotlinlang.org/docs/native-objc-interop.html and I don't know how to convert Swift/Obj-c class type to KotlinType.
j

Jan Holešovský

12/06/2023, 9:35 AM
What are you actually trying to achieve? It is possible to pass a function of a certain type as a parameter, but seems like you are searching for something more "universal"?
https://stackoverflow.com/a/70887422/16670548 shows such a passing of the function between Kotlin and Swift, maybe it'll be helpful
p

Pavel Lahoda

12/06/2023, 11:21 AM
I use for identification and need to be able to find my data by that identification. I have an annotation like that:
Copy code
annotation class Feature(
    val featureId: KClass<out Identificator>
)
that I use to mark my multiplatform objects and then on the client I should be able to get this object using getByFeature(feature: Identificator) I found a kind of ugly workaround I will have a function:
Copy code
fun getByFeature(identifier: Any)
And I will have to pass an instance of type. In the shared code will compare the class like this:
Copy code
var feature = features.firstOrNull {
    if (it.identifier != null) {
        it.identifier!!::class.qualifiedName == identifiedBy::class.qualifiedName
    }
    false
}
Don't like the need to create the instance, but still have no idea how to pass type as parameter
j

Jan Holešovský

12/06/2023, 3:48 PM
But this is all Kotlin, where does Swift come into the picture? Can you maybe describe the problem at a higher level?
p

Pavel Lahoda

12/06/2023, 3:49 PM
No it is not.
Copy code
fun getByFeature(identifier: Any)
This is an API that would get called from the iOS (Swift). I need to pass the type as a parameter. Both are defined in KMP, but call actually happens on the client
j

Jan Holešovský

12/06/2023, 3:58 PM
I see, this confused me, in Swift it is 'func', not 'fun' 😉 But I'm still missing the bigger picture - are you trying to create some kind of factory function in K/N that you can call from Swift, that would return you an instance of the class identified by the identifier? Or?
[Why I am asking - I'm not aware it would be possible to pass type as a parameter; but there are some tricks I'm aware of that might be helpful, depending on the use case.]
p

Pavel Lahoda

12/06/2023, 4:07 PM
OK, got it. I put there a signature as it is defined in KMP. It is called from Swift. Yeah it is a factory function, as I said the Class is used as identifier. There is another KMP class, that is annotated by a custom annotation, which has the identifier as parameter. Annotation types are quite limited, thus passing a type is pretty much only viable option. I need to be able to find another object (also in KMP). I have existing implementation where I use String identifiers, but don't like strings and want a different solution.
j

Jan Holešovský

12/06/2023, 4:11 PM
I see. So String would be my 1st suggestion for the factory 😉 But if you prefer types, the 'is' works across K/N and Swift - that might be a better choice than comparing the qualifiedName (which won't work when inheritance comes into play - but I suppose it is not your case here).
p

Pavel Lahoda

12/06/2023, 4:17 PM
I don't like Strings, especially if they are used cross-platform, this is not solution that works well with refactoring. I have no problem with implementation of the function, just don't know how to pass Type as parameter. Wander why KClass and KType is not mentioned at all in the interoperability documentation. It gets mapped to KotlinKClass and KotlinKType, but I don't know how do deal with these in Swift. But as I said, found a solution with passing an instance of such a class. Not ideal, but much better than Strings.
j

Jan Holešovský

12/06/2023, 4:30 PM
Yeah, as said, I don't think it is possible to pass the type as parameter. Another thing that comes to my mind is an enum class; but I suppose you considered that yourself too 😉 So I fear the thing you came up with is the only way.
p

Pavel Lahoda

12/06/2023, 4:32 PM
Hm, don't think enum would work as parameter of an annotation.
j

Jan Holešovský

12/06/2023, 4:33 PM
It IIRC does, if it is your only limitation
Copy code
annotation class Blah(val xx: XYZ = XYZ.A) {
    enum class XYZ { A, B, C }
}
p

Pavel Lahoda

12/06/2023, 4:41 PM
OK, this way it would work, but I don't want to have one huge enum class with all my IDs. Guess I will settle for what I have now. Weird that KClass is not mentioned in the documentation at all.
4 Views