Kotlin/Native与Swift互操作:生成接口同签名方法如何同时重写
你遇到的签名冲突是Kotlin/Native的ObjC互操作默认规则导致的。两个方法对应的原始ObjC选择器(Selector)并不相同,分别是centralManager:didDisconnectPeripheral:error:和centralManager:didFailToConnectPeripheral:error:,但Kotlin默认将ObjC方法的第一个选择器段作为Kotlin侧方法名,仅靠参数名区分后续选择器段,而Kotlin方法重载只校验参数类型不校验参数名,两个方法的参数类型完全一致,因此会出现签名冲突,仅能重写其中一个。
方案1:开启ObjC方法名前缀编译选项(推荐)
开启Kotlin/Native编译器的-Xobjc-generate-function-prefix-for-selector-parts选项后,编译器会将ObjC选择器的所有段拼接为Kotlin侧方法名,从根源解决签名冲突问题。
你需要在项目的build.gradle.kts中为所有iOS目标添加该编译参数,示例配置如下:
kotlin { // 按需添加你使用的所有iOS目标 listOf( iosArm64(), iosSimulatorArm64(), iosX64() ).forEach { iosTarget -> iosTarget.compilations.all { kotlinOptions.freeCompilerArgs += "-Xobjc-generate-function-prefix-for-selector-parts" } } }
配置同步并重新构建项目后,两个冲突方法的Kotlin侧签名会变为:
fun centralManagerDidFailToConnectPeripheral(central: CBCentralManager, didFailToConnectPeripheral: CBPeripheral, error: NSError?)fun centralManagerDidDisconnectPeripheral(central: CBCentralManager, didDisconnectPeripheral: CBPeripheral, error: NSError?)
此时即可分别重写两个回调方法。
注意:开启该选项后,所有ObjC协议映射的Kotlin方法名都会发生变化,之前已实现的其他ObjC协议方法需要同步调整方法名适配新命名规则。
方案2:自定义ObjC桥接代理
如果不想修改全局编译配置,可以在iOS原生侧实现一个中间CBCentralManagerDelegate代理类,将两个回调分别转发给Kotlin侧定义的两个不同命名的公开方法即可,无需修改Kotlin侧的ObjC互操作规则。
内容的提问来源于stack exchange,提问作者Anonymous

