Is reflection handled differently between Android ...
# multiplatform
a
Is reflection handled differently between Android and iOS with Kotlin Multiplatform? Accessing the any member val from KClass returns "Unresolved reference: <name>" when building the iOS variant, but doesn't complain for the Android variant. I've tried also adding the reflect dependency in case.
a
a
interesting. Is there any example on how to achieve instance creation from KClass on non-JVM platforms?
a
I'm not sure but I would think it is not possible.
s
Reflection in native is mostly non-existent. Projects like kotlinx-serialization use annotations and code generation to get the job done on iOS.
a
Got it, thanks
k
Kotlin/Native is a lot more like Swift than the JVM in that respect. Very little reflection and dynamic interaction with classes.
s
@Alberto Reflection is a form of meta programming. You may find that you can get similar results with Compiler Plugins, another form of meta programming that will be supported (eventually) on all Kotlin platforms.
a
Got it, I was trying to implement something like a component registry / service locator to be used across Android/iOS but sounds like may want to use something different, perhaps like DI via Koin, unless there's other recommendations
s
Koin builds its registry up with closures that construct objects rather than reflection.
z
I've had a good experience with Koin, though correct me if I'm wrong @Sam. I thought Koin does call
getKClass
somewhere internally
i ended up wrapping any swift objects that were passed into Koin with a kotlin object
s
My experience with it is only on Android. On iOS I use a Coordinator to build up my dependency graph and pass it into the ViewControllers/ViewModels.
k
I wrote the koin native implementation! It does use kclass, but reflection is just nowhere near as dynamic on native. I forget the details at the moment on how it resolves, but it’s different than the jvm for sure.
😍 1
👍 1
r
You actually can pass Swift things to Koin if you cast to
Any
first to avoid KClass issues, but then you lose type safety and need to use qualifiers to manually distinguish things. Much cleaner if you wrap in a Kotlin object.
m
@zsperske could you pls explain more in detail how do you “wrap swift objects into kotlin object” ?
z
via delegation
say you have a swift class
DatabaseDriverIos
that implements an interface you defined in kotlin called
DatabaseDriver
which you want to provide to Koin when your app starts
you can write a kotlin class in your iOSMain code that looks like
Copy code
class DatabaseDriverWrapper(private val databaseDriverImpl) : DatabaseDriver by databaseDriverImpl
👍 1
when you're about to feed Koin the classes it needs, you construct that wrapper and feed it in an instance of
DatabaseDriverIos
this was all actually suggested to me by @russhwolf (thanks again!), please correct me if I've overcomplicated it
r
For that specific use-case you might be overcomplicating things. If
DatabaseDriver
is a Kotlin type then as long as you cast to that in your Koin code you probably don't need the wrapper. eg you could define
Copy code
fun configureKoin(databaseDriver: DatabaseDriver) {
  startKoin(modules(module {
    ...
    single { databaseDriver }
  }))
}
and then call
configureKoin()
from Swift. But if
DatabaseDriverIos
doesn't implement a Kotlin interface then you'd want a wrapper like
class DatabaseDriverWrapper(val databaseDriverIos: DatabaseDriverIos)
to be able to bind it to Koin. (sorry to take this thread off the rails)
👍 2
m
Thanks for you answers @zsperske and @russhwolf. In my particular case I need to use AWS native libs with “nice” callback APIs so I’ve already gave up on putting them in the common part. My current implementation use technique “ServiceRegistry” with lambdas in the same manner as “DroidconApp”. Works fine, but I like the idea of wrapper seeding in iosMain, so I will give it an another try. Just for the sake of consinstency in an usage of Koin
116 Views