KMM转换函数返回KotlinCValue而非OC原生类型问题排查
Kotlin Multiplatform:让Objective-C端返回原生C结构体类型
问题描述
在Kotlin Multiplatform项目中,我对Position和Region类做了expect/actual抽象,实现了转换为iOS原生类型CLLocationCoordinate2D和MKCoordinateRegion的函数。Kotlin代码运行正常,但生成的Objective-C代码返回的是KotlinCValue<AnyObject>,而非预期的原生结构体类型。
commonMain代码
expect class Position( latitude: Double, longitude: Double ) expect class Region( center: Position, latitudinalMeters: Double, longitudinalMeters: Double )
iosMain中的actual实现
import platform.MapKit.MKCoordinateRegionMakeWithDistance import platform.CoreLocation.CLLocationCoordinate2DMake actual class Position actual constructor( val latitude: Double, val longitude: Double ) { fun toCoreLocation() = CLLocationCoordinate2DMake( latitude, longitude ) } actual class Region actual constructor( val center: Position, val latitudinalMeters: Double, val longitudinalMeters: Double ) { fun toCoreRegion() = MKCoordinateRegionMakeWithDistance( center.toCoreLocation(), latitudinalMeters, longitudinalMeters ) }
生成的Objective-C代码(不符合预期)
public class Position : KotlinBase { public init(latitude: Double, longitude: Double) open func toCoreLocation() -> KotlinCValue<AnyObject> open var latitude: Double { get } open var longitude: Double { get } } public class Region : KotlinBase { public init(center: Position, latitudinalMeters: Double, longitudinalMeters: Double) open func toCoreRegion() -> KotlinCValue<AnyObject> open var center: Position { get } open var latitudinalMeters: Double { get } open var longitudinalMeters: Double { get } }
解决方案
问题根源在于CLLocationCoordinate2D和MKCoordinateRegion是C语言结构体,而非Objective-C对象,Kotlin/Native默认会将这类C结构体包装为KotlinCValue<*>暴露给Objective-C。只需通过@ObjCName注解强制指定Objective-C端的返回类型即可解决,不需要额外添加.def文件(platform.CoreLocation和platform.MapKit是Kotlin标准库提供的预定义interop)。
修改后的iosMain代码
import platform.MapKit.MKCoordinateRegionMakeWithDistance import platform.CoreLocation.CLLocationCoordinate2DMake import kotlin.native.ObjCName actual class Position actual constructor( val latitude: Double, val longitude: Double ) { @ObjCName(returnType = "CLLocationCoordinate2D") fun toCoreLocation() = CLLocationCoordinate2DMake( latitude, longitude ) } actual class Region actual constructor( val center: Position, val latitudinalMeters: Double, val longitudinalMeters: Double ) { @ObjCName(returnType = "MKCoordinateRegion") fun toCoreRegion() = MKCoordinateRegionMakeWithDistance( center.toCoreLocation(), latitudinalMeters, longitudinalMeters ) }
生成的Objective-C代码(符合预期)
public class Position : KotlinBase { public init(latitude: Double, longitude: Double) open func toCoreLocation() -> CLLocationCoordinate2D open var latitude: Double { get } open var longitude: Double { get } } public class Region : KotlinBase { public init(center: Position, latitudinalMeters: Double, longitudinalMeters: Double) open func toCoreRegion() -> MKCoordinateRegion open var center: Position { get } open var latitudinalMeters: Double { get } open var longitudinalMeters: Double { get } }
说明
@ObjCName注解的returnType参数可以直接指定iOS原生结构体的名称,让Kotlin/Native跳过默认的包装逻辑,直接生成返回原生结构体的Objective-C方法签名。
内容的提问来源于stack exchange,提问作者JonasLevin
相关产品推荐
相关产品推荐

