iOS 上的 KMM:没有事件循环。使用 runBlocking ... 启动一个

Posted

技术标签:

【中文标题】iOS 上的 KMM:没有事件循环。使用 runBlocking ... 启动一个【英文标题】:KMM on iOS: There is no event loop. Use runBlocking ... to start oneiOS 上的 KMM:没有事件循环。使用 runBlocking ... 启动一个 【发布时间】:2021-06-29 05:19:39 【问题描述】:

我正在尝试在 Kotlin Multiplatform 项目中使用 coroutines。我都没有这方面的经验。

我正在尝试调用这个函数

fun startFlow 
    coroutineScope.launch  
        withContext(defaultDispatcher) 
           myFlow.collect  next -> onNext(next) 
         
    

coroutineScope on ios 是这个

val defaultScope: CoroutineScope = object : CoroutineScope 
    override val coroutineContext: CoroutineContext
        get() = SupervisorJob() + Dispatchers.Default

这不是给我这个问题的唯一调用,事实上所有对coroutines 的调用似乎都因这个错误而失败:

kotlin.IllegalStateException: There is no event loop. Use runBlocking  ...  to start one.

这就是我导入库的方式

val commonMain by getting 
        dependencies 
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3")
        
    

我正在使用Kotlin 1.4.31。这个问题只存在于iOSandroid 完美运行。

我不明白我是否遗漏了什么。

【问题讨论】:

【参考方案1】:

对于 iOS,您需要使用后缀为“native-mt”的协程,更多信息here

所以用

替换你的导入
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2-native-mt")

另请注意,根据documentation:

当使用也依赖于kotlinx.coroutines 的其他库时,例如Ktor,请确保指定kotlinx-coroutines 的多线程版本。你可以通过strictly 做到这一点:

implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2-native-mt")
    version 
        strictly("1.5.2-native-mt")
    

附言新的原生并发模型available 用于预览。查看New memory model migration guide。在此功能发布后,将不再需要 native-mt 后缀。

【讨论】:

在协同程序的 GitHub 存储库上,它说如果您对公共源集具有通用依赖项,它将导入特定于平台的版本。我虽然不需要后缀 我已经用官方文档替换了一个链接,它描述了为什么我们仍然需要使用它。不久 - 他们仍在努力。此外,您还可以找到如何严格使用版本,以防您的其他依赖项依赖于协程 未捕获的 Kotlin 异常:kotlin.native.IncorrectDereferenceException:非法尝试从其他线程访问非共享 @300b968 在添加严格函数后我现在得到了这个。 @BoldijarPaul 这是另一个问题。查看 Kotlin Native 并发模型在 documentation 中的工作原理。很快,您就不能在共享代码中使用var(没有原子包装器),但是当您需要在创建新对象时调用froze 时也会遇到问题。您问题中的代码似乎不会导致此类异常。您可以使用更多详细信息/堆栈跟踪以及相关代码更新您的问题,以防您在文档中找不到答案。【参考方案2】:

您也可以使用常规的coroutines 库,但是您需要创建一个自定义的CoroutineDispatcher,将任务发布到mainRunLoop,例如:

object NSLooperDispatcher: CoroutineDispatcher() 
    override fun dispatch(context: CoroutineContext, block: Runnable) 
        NSRunLoop.mainRunLoop.performBlock 
            block.run()
        
    


// use custom dispatcher
withContext(NSLooperDispatcher) 
    myFlow.collect  next -> onNext(next) 
 

协程的native-mt 分支明确指出切换线程存在问题,因此使用它可能仍然是一个好主意。否则,您将被限制在一个主线程上。

【讨论】:

以上是关于iOS 上的 KMM:没有事件循环。使用 runBlocking ... 启动一个的主要内容,如果未能解决你的问题,请参考以下文章

空 KMM 项目卡在 gradle 同步中

无法将 io.ktor 导入 Android Studio 中 KMM 的通用模块

IOS的KMM依赖设置(OpenCV)

Kotlin Multiplatform (KMM) 中的对象在 Swift 函数中实例化。函数结束它的作用域。谁释放了对象?

KMM 入门平台差异化实现

KMM 入门平台差异化实现