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

Kotlin Multiplatform Ktor iOS端POST请求失败排查求助

KMP+Ktor iOS端POST请求报错「类/文件初始化错误」的排查与修复

问题原因

该错误源于iOS端Kotlin Native运行时与JVM的差异,主要集中在序列化配置、Ktor客户端初始化、协程调用方式三个核心环节,Android端JVM对实验性API、可变字段的兼容性更强,因此未触发异常。

核心失误点

  1. 实验性序列化注解的兼容性问题:使用@ExperimentalSerializationApi和@ExperimentalStdlibApi,Kotlin Native对实验性API的支持远不如JVM稳定,会触发类初始化失败。
  2. Ktor客户端序列化插件配置缺失:共享模块的Ktor客户端未针对iOS端配置完整的Json序列化插件,或依赖未同步添加。
  3. Suspend函数的Swift调用方式错误:手动传递callback参数,违背了Kotlin suspend函数暴露给Swift的原生调用逻辑,导致协程上下文初始化异常。
  4. 数据类可变字段的序列化冲突:DestinationsResponse中使用var修饰字段,Kotlin Native对可变字段的序列化反射处理存在兼容性问题。

修复方案

1. 移除实验性注解,改用稳定序列化API

将数据类的实验性注解移除,同时将var改为val(不可变字段在Kotlin Native序列化中更稳定):

@Serializable
data class DestinationsResponse(
    val ok: Boolean = false,
    val error: ErrorInfo? = null,
    val data: List<BusStop>? = emptyList()
) {
    fun toJson() = Json.encodeToString(this)
}

2. 统一配置跨平台Ktor客户端

使用expect/actual为Android和iOS分别配置Ktor引擎,并确保添加兼容的序列化插件:

// 共享模块定义expect函数
expect fun createHttpClient(): HttpClient

// Android模块实现
actual fun createHttpClient(): HttpClient = HttpClient(OkHttp) {
    install(ContentNegotiation) {
        Json(Json {
            ignoreUnknownKeys = true // 忽略服务端返回的未知字段
            isLenient = true
            encodeDefaults = true
        })
    }
}

// iOS模块实现
actual fun createHttpClient(): HttpClient = HttpClient(Darwin) {
    install(ContentNegotiation) {
        Json(Json {
            ignoreUnknownKeys = true
            isLenient = true
            encodeDefaults = true
        })
    }
}

3. 修正Suspend函数定义与Swift调用方式

简化Kotlin端suspend函数,直接返回结果(而非嵌套callback),Swift端使用自动生成的completionHandler处理返回值:

// 共享模块API方法修改
suspend fun destinations(departure: DeparturePoint): DestinationsResponse {
    return try {
        val param = mapOf(
            "server" to departure.server,
            "departure" to departure.id,
        )

        val result = createHttpClient().post("$baseUrl/api/v2/routes/destinations") {
            contentType(ContentType.Application.Json)
            setBody(param)
        }.body<DestinationsResponse>()

        Instance.api.destinations = result.data ?: emptyList()
        result
    } catch (e: Exception) {
        log.e { "~~~ destinations exception: ${e.message}" }
        DestinationsResponse()
    } catch (t: Throwable) {
        log.e { "~~~ destinations throwable: ${t.message}" }
        DestinationsResponse()
    }
}
// Swift端调用修改
Instance.companion.api.destinations(departure: departurePoint) { response, error in
    if let validResponse = response {
        // 处理正常返回结果
    } else if let err = error {
        // 处理错误
    }
}

4. 验证依赖配置

确保共享模块的build.gradle.kts中添加了完整的跨平台依赖:

val commonMain by getting {
    dependencies {
        implementation("io.ktor:ktor-client-core:2.3.10")
        implementation("io.ktor:ktor-client-content-negotiation:2.3.10")
        implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.10")
        implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
    }
}

val iosMain by getting {
    dependencies {
        implementation("io.ktor:ktor-client-darwin:2.3.10")
    }
}

val androidMain by getting {
    dependencies {
        implementation("io.ktor:ktor-client-okhttp:2.3.10")
    }
}

内容的提问来源于stack exchange,提问作者Yar Geel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 22:28:28