I'm working on a KMM library, using cinterop and h...
# multiplatform
c
I'm working on a KMM library, using cinterop and having some issues when I export my library to a framework 🧵
I cant seem to export a typealias to the headers of my framework. Heres an example to demonstrate: Consider an expect interface is defined in `commonMain`:
Copy code
// commonMain
expect interface MyCoolInterface
And the implementations look like this:
Copy code
// androidMain
actual interface MyCoolInterface

// iosMain
actual typealias MyCoolInterface = MyCinteropProtocol
Neither
MyCoolInterface
nor
MyCinteropProtocol
is exported to the headers. I've found this YouTrack issue which confirms that this is not yet supported. However, wondering if anyone has any suggestions for working around this?
What I've tried: • Defining
MyCoolInterface
as an
interface
on iosMain (rather than a typealias) (fails with error Only classes are supported as subtypes of Objective-C types) • Defining
MyCoolInterface
as a class in all modules. (fails with error Kotlin implementation of Objective-C protocol must have Objective-C superclass (e.g. NSObject)
l
What is the end goal? Are there any common methods of the interface that you want to be able to call from common code? Are you trying to detect if an object implements this interface?
c
Yes I want to detect if an object implements this interface. My KMM library
MyLibrary
exposes the interface
MyInterface
which can be implemented in the common code of a KMM application
MyApp
. I'm also writing some swift utilities in a separate swift library
SwiftUtils
which is dependant on the
MyLibrary
framework, and uses
MyInterface
for example:
Copy code
class MySwiftClass {
    func doWorkWith(_ object: MyInterface) {}
}
The issue I have is that the ObjC declaration of
MyInterface
is slightly different in
MyApp
(iOS) vs
SwiftUtils
(iOS), I suspect due to how the frameworks are generated. (they have different prefixes). So I'm trying to generate the interface in ObjC, then using cinterop add it to both the library and the swift utils. Hopefully this makes sense!
I guess the other alternative would be if theres a way to specify what the ObjC name of a class/interface should be?
or if theres a way to prevent the baseName prefix being added to transitive dependencies?
r
Your cinterop approach sounds good. Why do you need the KMM library to expose the ObjC protocol? Can't you add a dependency to the ObjC code from your Swift library?
FYI in Kotlin 1.8.0 you can control the exact names with the
@ObjCName
annotation.
Though I think in this case the cinterop approach would be better.
c
thanks @Rick Clephas! I need both the swift library and the app implementing the KMM library to have access to the same protocol. I did not know about
@ObjName
that might solve my problems 🤔
my issue however is when I implement the KMM library in a KMM app, the protocol gets named
SharedModuleNameProtocolName
(so long as i set
transitiveExport = true
)
but in the swift library its getting named
LibraryNameProtocolName
. Hence I started looking into cinterop to get around this
r
In that case you could depend on an ObjC library with the protocol from KMM and Swift. I did something similar with KMM-ViewModel.
KMMViewModelCoreObjC
declares a protocol (
KMMVMViewModelScope
) which is used in Kotlin via cinterop and in the Swift library
KMMViewModelCore
.
c
got it thanks for the reference. I think thats what I'm trying to do actually
I'll go back and take a look at where I might be going wrong 🙌
nice to know of the
@ObjCName
annotation coming up in 1.8 though!
r
Indeed, I think it can be quite useful (especially combined with the
@HidesFromObjC
and
@ShouldRefineInSwift
annotations)!
r
I've been reading this @Ciaran Sloan, were u able to make this work? I'm a bit lost with ShouldRefineInSwift annotation..
c
hey Roberto 👋🏼 I was able to get c-interop working for me, but it unfortunately didn't suit my use case here for what I was trying to achieve. I didn't end up needing the annotations
152 Views