I have an Android/iOS project which has a Koin mod...
# multiplatform
l
I have an Android/iOS project which has a Koin module in
shared
: CommonModule.kt:
Copy code
val commonModule = module {
    single<HttpClient> { TmdbApi.createHttpClient() }
    single<TmdbApi> { TmdbApi(client = get()) }
}

fun initKoin() = startKoin {
    modules(CommonModule.module)
}
In the Android app I can inject dependencies very easily:
Copy code
val tmdbApi: TmdbApi by inject()
In the iOS AppDelegate I call
CommonModuleKt.doInitKoin()
How can I inject the dependencies in the iOS
ContentView
?
o
Hello, I borrowed some of this from https://github.com/touchlab/KaMPKit : add these to ios module:
Copy code
fun Koin.get(objCClass: ObjCClass, parameter: Any): Any {
    val kClazz = getOriginalKotlinClass(objCClass)!!
    return get(kClazz) { parametersOf(parameter) }
}


fun Koin.get(objCClass: ObjCClass): Any {
    val kClazz = getOriginalKotlinClass(objCClass)!!
    return get(kClazz)
}

fun Koin.get(objCProtocol: ObjCProtocol): Any {
    val kClazz = getOriginalKotlinClass(objCProtocol)!!
    return get(kClazz)
}
And these to Xcode project:
Copy code
var koin: Koin_coreKoin = {
    let doOnStartup = { print("Hello from iOS/Swift!") }
    
    return KoinIOSKt.doInitKoinIos(doOnStartup: doOnStartup).koin
}()


func inject<T : AnyObject>() -> T {
    return koin.get(objCClass: T.self) as! T
}
after that, you can call
*private* *var* foo: Foo = inject()
note that foo is a class. not interface.
if you want to inject an interface use
Copy code
koin.get(objCProtocol: Bar.self) as! Bar
r
FYI we're moving away from doing that sort of thing because exporting dependencies into Swift can be bad for binary size
👀 2
w
@russhwolf I understand the point (and even agree TBH), but that comes from the iOS team? I remember in the past discussing app sizes, and from a couple of different iOS teams they were not worried about it - while the Android teams I've been in touch all were always trying to reduce the app size 👀
o
@russhwolf what is the alternative?
r
of course it'll vary by team and project. But we had one client who had something like a factor of 3 difference in kotlin binary size when explicitly exporting. On KaMPKit the impact is much smaller.
👀 1
The alternative is to explicitly define the interface you want to expose to iOS. For instance, we added this function in KaMPKit to wrap the koin usage we wanted from Swift, so we can call that directly and don't need to explicitly export the library. This way the only library classes that are in the Obj-C header are the ones that are in our shared module's public API.
o
I'm sorry, I'm asking because I didn't understand. Why is it different from using koin.get? Isn't koin still exported?
l
Thank you very much @russhwolf for a thorough explanation and links. I will take a look at KaMPKit and try to implement it in a similar way.
r
Only the bits of Koin that are part of the shared module public API are exported, rather than the whole library.
It's maybe a bad example and we could think about encapsulating it better. But the general point is you might not want to leak more into the public API of your Swift/Kotlin boundary than you have to.
o
well, I didn't use this export 😕 Neither did KaMPKit right? How is it different?
r
Kampkit did previously, but doesn't anymore