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

KMM项目iOS端无法获取Kotlin仓库数据,报EXC_BAD_ACCESS错误求助

KMM项目iOS端获取数据抛出EXC_BAD_ACCESS异常排查与解决

问题背景

Kotlin端可正常获取数据,但iOS端调用时抛出异常:Thread 4: EXC_BAD_ACCESS (code=EXC_I386_GPFLT),崩溃点位于Swift代码的强制类型转换行。

相关代码

Kotlin端仓库代码

suspend fun getRestaurantsOrders(): CommonFlow<List<Order>> {
        val userId = appService.currentUser!!.id
        val restaurant = realm.query<Restaurant>("userID = $0", userId).first().find()!!
        return withContext(Dispatchers.Default) {
            realm.query<Order>("restaurantID = $0 && totalQuantity > 0 SORT(discount DESC)", restaurant._id.toString())
                .asFlow().map {
                    it.list
                }.asCommonFlow()
        }
    }

iOS端Swift调用代码

func getOrdersList()
    {
        Task{
            do{
                try await repo.getRestaurantsOrders().watch(block: {orders in

                    self.restaurantActiveOrdersList = orders as! [Order] //崩溃位置

                })
            }catch{
                print("error")
            }
        }
    }

问题分析与解决方法

1. 强制类型转换不兼容

KMM传递的List<Order>在Swift中对应KotlinList<Order>,而非原生Swift数组[Order],直接用as!强制转换会触发类型不匹配崩溃。

解决:
将Kotlin集合转为Swift原生数组,同时避免强制转换风险:

try await repo.getRestaurantsOrders().watch(block: { orders in
    // 安全转换后转成Swift数组
    guard let kotlinOrders = orders as? KotlinList<Order> else {
        print("类型转换失败")
        return
    }
    self.restaurantActiveOrdersList = Array(kotlinOrders)
})

2. Realm对象线程绑定问题

Realm查询返回的Order是线程绑定的托管对象,Kotlin端用Dispatchers.Default调度后,对象可能在后台线程,iOS端直接访问会触发内存访问异常。

解决:

  • 方案一:Kotlin端映射为非托管数据类
    将Realm的Order对象映射为普通Kotlin数据类,脱离Realm线程绑定:
// 先定义非托管数据类
data class OrderDto(
    val id: String,
    val totalQuantity: Int,
    val discount: Double,
    // 其他字段
)

// 修改仓库方法
suspend fun getRestaurantsOrders(): CommonFlow<List<OrderDto>> {
    val userId = appService.currentUser?.id ?: throw IllegalStateException("用户未登录")
    val restaurant = realm.query<Restaurant>("userID = $0", userId).first().find() ?: throw IllegalStateException("未找到餐厅")
    return withContext(Dispatchers.Default) {
        realm.query<Order>("restaurantID = $0 && totalQuantity > 0 SORT(discount DESC)", restaurant._id.toString())
            .asFlow()
            .map { result ->
                // 映射为非托管对象
                result.list.map { order ->
                    OrderDto(
                        id = order._id.toString(),
                        totalQuantity = order.totalQuantity,
                        discount = order.discount
                    )
                }
            }
            .asCommonFlow()
    }
}
  • 方案二:Swift端确保主线程操作
    如果坚持使用Realm对象,需在主线程处理回调结果:
try await repo.getRestaurantsOrders().watch(block: { orders in
    DispatchQueue.main.async {
        self.restaurantActiveOrdersList = Array(orders as! KotlinList<Order>)
    }
})

3. Kotlin端强制解包风险

代码中currentUser!!和restaurant!!的强制解包,若为空会抛出未捕获异常,导致iOS端崩溃。

解决:
替换为安全处理,抛出明确异常或返回空:

suspend fun getRestaurantsOrders(): CommonFlow<List<Order>> {
    val userId = appService.currentUser?.id ?: throw IllegalStateException("当前无登录用户")
    val restaurant = realm.query<Restaurant>("userID = $0", userId).first().find() ?: throw IllegalStateException("未找到关联餐厅")
    return withContext(Dispatchers.Default) {
        realm.query<Order>("restaurantID = $0 && totalQuantity > 0 SORT(discount DESC)", restaurant._id.toString())
            .asFlow().map { it.list }
            .asCommonFlow()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 08:42:22