iOS 深度集成与互操作
源:Kotlin Multiplatform iOS 集成官方文档
将 Kotlin 共享层集成到 iOS 应用中,不仅仅是调用几个函数。我们需要确保共享层能与 SwiftUI 的声明式 UI 和 Apple 的异步并发模型(Swift Concurrency)完美协作。
Kotlin Flow 与 Swift Concurrency
原生环境下,Swift 开发者更习惯使用 Async/Await 或 Combine。
导出 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 中我们有 ViewModel 和 lifecycleScope。在 iOS 中,我们需要手动关联生命周期。
绑定到 SwiftUI 生命周期
swift
struct UserView: View {
@StateObject var viewModel = SharedViewModel()
var body: some View {
Text("Hello")
.onAppear {
viewModel.startObserving()
}
.onDisappear {
viewModel.stopObserving()
}
}
}导出接口的最佳实践
为了让导出的 Framework 对 Swift 更友好:
- 避免重载: 如前所述,尽量使用明确的函数名。
- 密封类处理: Kotlin 的
Sealed Class在 Swift 中会被转换为带有is判断的类。使用 SKIE 可以将其转换为真正的 SwiftEnum。 - 可选值处理: 确保 Kotlin 侧正确标注可空性,它会准确映射为 Swift 的
Optional。
构建动态 XCFramework
为了支持最新的 Xcode 预览和混合架构(Arm64 + x64),建议导出 XCFramework 而不是传统的 Framework。
kotlin
// build.gradle.kts
kotlin {
iosTarget.binaries.framework {
export(project(":shared"))
}
}