You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 20:40:18