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

KMM向iOS抛出自定义Throwable:除返回对象外的更优方案?

解决KMM自定义Throwable在iOS端无法直接获取的问题

在KMM中抛出自定义Throwable时,iOS端的completionHandler只能接收到通用的NSError/Error对象,无法直接获取自定义异常的专属属性(比如示例里的code)。虽然可以通过让updateData()直接返回CustomError对象来实现需求,但以下几种方案更符合KMM跨平台设计的最佳实践:

方案1:用密封类封装结果(Result模式)

这是KMM跨平台处理成功/失败场景的标准方案,通过密封类统一封装操作结果,避免依赖异常抛出机制,同时让iOS端能直接获取自定义错误信息。

KMM代码实现

sealed class Result<out T> {
    data class Success<out T>(val data: T) : Result<T>()
    data class Failure(val error: CustomError) : Result<Nothing>()
}

class CustomError(val message: String, val code: Int)

class Greetings {
    suspend fun updateData(): Result<Unit> {
        return Result.Failure(CustomError("This is the customised error msg", 123))
    }
}

iOS代码调用

Greetings().updateData { result in
    switch result {
    case .success:
        // 处理成功逻辑
        print("Update succeeded")
    case .failure(let error):
        // 直接获取自定义错误的属性
        print("Error message: \(error.message), code: \(error.code)")
    }
}

方案2:扩展NSError注入自定义属性

如果仍想保留异常抛出的方式,可以通过Kotlin的expect/actual机制,把自定义异常的属性注入到iOS端NSError的userInfo字典中,让iOS端能从通用Error中提取自定义信息。

KMM代码实现

// commonMain
expect class CustomError(message: String, code: Int) : Throwable

// iosMain
import platform.Foundation.NSError
import platform.Foundation.NSLocalizedDescriptionKey

actual class CustomError actual constructor(message: String, val code: Int) : Throwable(message) {
    override fun fillInStackTrace(): Throwable {
        // 将自定义code注入到NSError的userInfo中
        val userInfo = mapOf(
            "customErrorCode" to code,
            NSLocalizedDescriptionKey to message
        )
        return NSError(domain = "com.yourdomain.customerrors", code = code, userInfo = userInfo) as Throwable
    }
}

class Greetings {
    @Throws(Throwable::class)
    suspend fun updateData() {
        throw CustomError("This is the customised error msg", 123)
    }
}

iOS代码调用

Greetings().updateData { error in
    if let nsError = error as NSError? {
        let customCode = nsError.userInfo["customErrorCode"] as? Int ?? -1
        let errorMessage = nsError.localizedDescription
        print("Error message: \(errorMessage), custom code: \(customCode)")
    }
}

方案3:序列化自定义异常

通过Kotlinx Serialization将自定义异常序列化,抛出时传递序列化后的内容,iOS端反序列化获取完整信息。这种方案适合需要传递复杂错误结构的场景,但需要额外配置序列化插件。

KMM代码实现

首先在build.gradle.kts中添加序列化依赖:

plugins {
    kotlin("multiplatform")
    kotlin("plugin.serialization") version "1.9.20"
}

// 在commonMain依赖中添加
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.0")

然后定义可序列化的自定义异常:

import kotlinx.serialization.Serializable

@Serializable
class CustomError(val message: String, val code: Int) : Throwable(message)

class Greetings {
    @Throws(Throwable::class)
    suspend fun updateData() {
        throw CustomError("This is the customised error msg", 123)
    }
}

iOS代码调用

借助Kotlinx Serialization的iOS端支持,将接收到的NSError中的异常信息反序列化:

import KotlinxSerialization

Greetings().updateData { error in
    if let nsError = error as NSError?,
       let errorData = nsError.userInfo["KotlinException"] as? Data,
       let customError = try? JSONDecoder().decode(CustomError.self, from: errorData) {
        print("Error message: \(customError.message), code: \(customError.code)")
    }
}

内容的提问来源于stack exchange,提问作者Ashwani Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 20:35:25