I’m thinking about migrating to KMP. However, I ha...
# multiplatform
u
I’m thinking about migrating to KMP. However, I have this feature which depends on a library with has both android and ios counterparts, but obviously not a kmp library. On ios the library is distributed as a SPM package (no cocoapods). Can kmp handle this (such that I’d include the spm package in iosMain and implement actuals with it Or am I out of luck?
s
If you want to make a KMP library (for other KMP libraries/apps) that uses this SPM based Swift-library, you have to wrap the Swift-library calls with Objective-C calls and expose these Objective-C to KMP using "cinterop".
u
hmm but wrap them where exactly? some new repository where I pull that in via spm?
s
A lot to explain here in this thread, but here's a Medium article https://medium.com/kodein-koders/create-a-kotlin-multiplatform-library-with-swift-1a818b2dc1b0 It's a bit old, but Google "KMP cinterop" to find the latest.
In short, your KMP library will contain an iOS project and a cinterop module. The iOS project will import the SPM library and add Objective-C code to call the Swift code of this SPM library. The cinterop will then make this Objective-C code available to KMP.
If this is all for one KMP based app and you're never planning on making this a library/module, don't go this cinterop route... (quite complex). Instead just import the SPM library in your iOSApp/Xcode code, implement an interface(protocol) defined by "commonMain" and inject the Swift implementation of this interface into the common KMP code (plain old DI).
u
hmm..yea, I was just about to say this is not worth it 😄
or maybe, if I were to republish the library via cocoapods? then I could cleanly pull that in, no?
s
Yup. Only do the cinterop stuff if you have multiple apps planning to use it. Otherwise, just use DI
Cocoapods: I never tried that. I guess that could be possible.
u
gotcha, thank you
ehm, i'm thinkigm aboit this more, im new to kmp if kmp exposes a interface
Foo
via kmp, and you said have swift implement it using the spm library how do I then pop the
SwiftFoo
back into the DI graph? will koin/kotlin-inject be available at swift level?
s
You just call a function back into common KMP. That function would take a parameter that has the type of the interface and when calling it you provide an implementation of that interface as its argument .
Koin can be used in Swift.
u
soe something like
expect createFoo(): Foo
in common, then actualized in swift?
s
Possibly, but instead use plain interfaces When using "manual" DI: In commonMain: interface SomeLibraryApiInterface { ... } Eg in DI.kt: fun diSetSomeLibraryApiInterface(if: SomeLibraryApiInterface) {....} fun getSomeLibraryApiInterface() {...} Swift: class SomeLibraryApiInterfaceImpl: SomeLibraryApiInterface {...} And on start of your app: DIKt.diSetSomeLibraryApiInterface(SomeLibraryApiInterfaceImpl())
u
yea.. im not planing on using koin, so not sure how would that work in dagger/kotlin-inject, whose are compile time validated 😕
s
Dagger is JVM only and kotlin-inject is KMP, but only for (kotlin) code in the 'shared' module
u
yea I know
s
But you can manually inject it from swift
u
but how, if dependencies need to be provided at compile-time so to speak, if its created at runtime, then it needs to be a parameter of the Component
I like the
expect fun create: Foo
for this, so the library calls the function essentially
s
Provide a 'wrapper' kotlin implementation via kotlin-inject, that uses a delegate that is being assigned 'manually' by Swift code
Don't use expect/actual here. Just plain old dependency injection
u
so a public setter?
Copy code
class Wrapper: Foo {
    var delegate: Foo
    ...
}
and then
DI.wrapper.delegate = ..
in ios' AppDelegate?
s
Yup, something like it.
u
clunky but I guess it would work yea
s
But dirty, not compile time checked, but it works
u
I wonder, if this was to be done cleanly, what everything would need to be in place by jetbrains?
swift export
but spm support as well?
s
It involves Swift that would need to provide the implementation.... I wouldn't count on Apple cooperating here 😁
u
but if I could simply import spm module like now I can cocapod, I could just
actual
the interface, no?
s
SPM dependencies in addition to cocoapods... That would be possible by JetBrains, but that would be lot of work
u
I mean.. if cocoapod was possible.. but cocoapods are being dropped by everyone I know on ios
s
Maaaaaaybe when the Swift-Export tool gets fully developed then something may be possible
Cocoapod is Objective-C....
u
is it? I'm using Alamofire via cocoapods and Im pretty sure thats swift
s
But interoperability is only with a pod's Objective-C code.... Not swift
u
oh
s
Eg you can't use a String in shared/iosMain, but you can use NSString...
u
I see, wasn't aware, makes sense
s
But swift interoperability is slowly improving... Who knows in the future 😀
u
I kind of worry about shit just burning down if apple notices or something like that
s
IIRC, Swift language spec is open source
u
hmm..true
s
Xcode, that builds Swift (and Objective-C) is proprietary. But then again its interface (CLI) is public (and used in many CI/CD/DevOps pipelines). This makes stability more likely.
u
but swift compiler isnt, no?