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

KMM项目WebSocket代码Android正常,iOS报Unresolved reference: IO错误

问题原因

编译错误Unresolved reference: IO的核心原因是:Dispatchers.IO是JVM平台专属的协程调度器,Kotlin/Native(iOS目标平台)的协程库并没有提供这个调度器实现,因此在KMM的common模块代码中直接引用会导致iOS编译失败。

解决方法

1. 替换为多平台兼容的调度器

把Dispatchers.IO替换成跨平台通用的Dispatchers.Default,同时建议搭配SupervisorJob()创建协程作用域——这样单个子协程出现异常时,不会导致整个作用域被取消,更适合WebSocket这类长连接场景:

private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())

Dispatchers.Default在iOS和Android平台都有稳定实现,既能处理IO密集型任务,也能应对计算密集型场景,完全可以替代Dispatchers.IO的跨平台需求。

2. 额外代码优化

  • 修正拼写错误:把参数initRecieve改成initReceive,保持命名一致性
  • 完善关闭逻辑:先关闭WebSocket会话再关闭客户端,避免资源泄漏:
fun close() {
    scope.launch {
        session?.close(CloseReason(CloseReason.Codes.NORMAL, "Client closed session"))
    }
    scope.cancel()
    client.close()
}
  • 确认依赖:在common模块的build.gradle.kts中,确保引入了多平台协程核心依赖:
sourceSets {
    val commonMain by getting {
        dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
            // 其他依赖...
        }
    }
}
修正后的完整代码
import com.bokutotu.dateappmobile.model.*
import io.ktor.client.*
import io.ktor.client.plugins.websocket.*
import io.ktor.http.*
import io.ktor.websocket.*
import kotlinx.coroutines.*
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

expect fun wsClient(url: String, config: HttpClientConfig<*>.() -> Unit = {}): HttpClient

class WsChat(
    private val host: String = "127.0.0.1",
    private val port: Int = 8080,
    private val chatId: Int,
    private val userId: Int,
    private val initReceive: (String) -> Unit,
    private val onReceive: (String) -> Unit
) {
    private val client = wsClient(host)
    private var session: DefaultClientWebSocketSession? = null
    private val sessionPromise = CompletableDeferred<DefaultClientWebSocketSession?>()
    private var initialMessageReceived = false
    // 替换为多平台兼容的协程作用域
    private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())

    init {
        scope.launch {
            initSession()
        }
    }

    private suspend fun initSession() {
        client.webSocket(
            method = HttpMethod.Get,
            host = host,
            port = port,
            path = "/message/$chatId/$userId"
        ) {
            session = this
            sessionPromise.complete(this)
            initReceivePipeline()
        }
    }

    private suspend fun initReceivePipeline() {
        val session = sessionPromise.await()
        session?.let {
            for (frame in it.incoming) {
                frameHandler(frame) { receivedText ->
                    if (!initialMessageReceived) {
                        initialMessageReceived = true
                        initReceive(receivedText)
                    } else {
                        onReceive(receivedText)
                    }
                    println("here")
                }
            }
        }
    }

    private fun frameHandler(frame: Frame, receiveFunc: (String) -> Unit) {
        when (frame) {
            is Frame.Text -> {
                val receivedText = frame.readText()
                receiveFunc(receivedText)
            }
            else -> println("Unexpected Frame format")
        }
    }

    fun send(newMessage: NewMessageJson) {
        val json = Json.encodeToString(newMessage)
        scope.launch {
            val session = sessionPromise.await()
            session?.send(Frame.Text(json))
        }
    }

    fun close() {
        // 先关闭WebSocket会话,再取消作用域和客户端
        scope.launch {
            session?.close(CloseReason(CloseReason.Codes.NORMAL, "Client closed session"))
        }
        scope.cancel()
        client.close()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:22:05