首页 > 解决方案 > 如何冻结在 Swift 中创建的 Kotlin 对象?

问题描述

我正在使用带有 native-mt 协程支持和 Ktor 库的 Kotlin-Native。我有几个挂起的函数,它们接收使用构建器模式构建的对象。我知道我需要在 main/ui 线程上调用挂起的函数。但是,我不能保证将在该线程上创建构建器对象。我的理解是,在将它们发送到主线程以使用挂起函数调用之前,它们需要被冻结。那是对的吗?

例如,这将失败,因为查询对象尚未被冻结:

    func loadData() {
        DispatchQueue.global(qos: .background).async {
            let query = CustomerQuery().emails(value: ["customer@gmail.com"])
            self.fetchCustomersAndDoSomething(query: query)
        }
    }
    func fetchCustomersAndDoSomething(query: CustomerQuery) {
        DispatchQueue.main.async {
            self.mylibrary.getCustomers(query: query) { response, err in
                // do something with response
            }
        }
    }

如果这是真的,我是否正确,我需要为每个这样的对象添加一个方法才能“冻结”它,因为从导入我的库的 Swift 代码中似乎无法访问freeze()Kotlin 函数?Freezing.kt由于冻结仅适用于 iOS 代码,而 Android 代码不需要它,这使情况变得更加复杂。

有没有一种更简单的方法可以将 Swift 创建的 Kotlin 对象传递给挂起的函数,而无需在主线程上创建这些对象?

标签: swiftkotlinkotlin-coroutineskotlin-multiplatform

解决方案


在 Kotlin/Native 世界中,每当您在线程之间共享对象时,如果您不打算制作它们,则必须确保它们被冻结(不可变)@ThreadLocal。Android 是个例外,因为 JVM 没有那么严格,让我们在线程之间共享可变对象。

你有两个选择:

  1. 要么公开一个freeze()函数并使用它
  2. freeze()共享代码中的每个传入对象

另外,如果您不冻结,可能会碰到IncorrectDereferenceException,这意味着您正在尝试共享可变/非冻结状态


推荐阅读