Skip to content

iOS 深度集成与互操作

源:Kotlin Multiplatform iOS 集成官方文档

将 Kotlin 共享层集成到 iOS 应用中,不仅仅是调用几个函数。我们需要确保共享层能与 SwiftUI 的声明式 UI 和 Apple 的异步并发模型(Swift Concurrency)完美协作。

Kotlin Flow 与 Swift Concurrency

原生环境下,Swift 开发者更习惯使用 Async/AwaitCombine

导出 Flow 供 Swift 使用

在 Kotlin 侧,我们通常提供一个包装类,因为 Swift 目前还不能完美地直接处理泛型流。

kotlin
// commonMain
class FlowWrapper<T : Any>(private val flow: Flow<T>) {
    fun subscribe(
        onEach: (T) -> Unit,
        onCompletion: (Throwable?) -> Unit
    ): Job {
        return flow.onEach { onEach(it) }
            .catch { onCompletion(it) }
            .onCompletion { onCompletion(null) }
            .launchIn(CoroutineScope(Dispatchers.Main))
    }
}

在 Swift 侧(利用 SKIE 插件可自动生成):

swift
// Swift 调用示例
Task {
    for await value in viewModel.userList {
        self.users = value
    }
}

生命周期感知

在 Android 中我们有 ViewModellifecycleScope。在 iOS 中,我们需要手动关联生命周期。

绑定到 SwiftUI 生命周期

swift
struct UserView: View {
    @StateObject var viewModel = SharedViewModel()

    var body: some View {
        Text("Hello")
            .onAppear {
                viewModel.startObserving()
            }
            .onDisappear {
                viewModel.stopObserving()
            }
    }
}

导出接口的最佳实践

为了让导出的 Framework 对 Swift 更友好:

  1. 避免重载: 如前所述,尽量使用明确的函数名。
  2. 密封类处理: Kotlin 的 Sealed Class 在 Swift 中会被转换为带有 is 判断的类。使用 SKIE 可以将其转换为真正的 Swift Enum
  3. 可选值处理: 确保 Kotlin 侧正确标注可空性,它会准确映射为 Swift 的 Optional

构建动态 XCFramework

为了支持最新的 Xcode 预览和混合架构(Arm64 + x64),建议导出 XCFramework 而不是传统的 Framework。

kotlin
// build.gradle.kts
kotlin {
    iosTarget.binaries.framework {
        export(project(":shared"))
    }
}