Kotlin/Native 开发 Apple framework——教程
Kotlin/Native 提供与 Swift/Objective-C 的双向互操作性,允许在 Kotlin 代码中使用 Objective-C framework 和库,以及在 Swift/Objective-C 代码中使用 Kotlin 模块。本教程将指导你创建自己的 framework,并学习如何在 macOS 和 iOS 上的 Swift/Objective-C 应用程序中集成 Kotlin/Native 代码。
本教程内容包括:
- 创建一个 Kotlin 库并将其编译为 framework
- 检查生成的 Swift/Objective-C API 代码
- 在 Objective-C 中使用 framework
- 在 Swift 中使用 framework
对于小型项目,可以使用命令行生成 Kotlin framework,但对于大型项目,推荐使用构建系统如 Gradle,以提高可伸缩性。Kotlin/Native 通过 Kotlin 多平台插件支持 Gradle 构建系统。注意,如果使用 Mac 并需要开发 iOS 或其他 Apple 平台应用,需先安装 Xcode Command Line Tools。
创建一个 Kotlin 库
首先,创建一个 Kotlin 库,Kotlin/Native 编译器会将其编译为适用于 macOS 和 iOS 的 framework,包含所有必要的声明和二进制文件。
步骤:
- 在
src/nativeMain/kotlin目录中创建lib.kt文件,并添加以下库代码:
package example
object Object {
val field = "A"
}
interface Interface {
fun iMember() {}
}
class Clazz : Interface {
fun member(p: Int): ULong? = 42UL
}
fun forIntegers(b: Byte, s: UShort, i: Int, l: ULong?) { }
fun forFloats(f: Float, d: Double?) { }
fun strings(str: String?) : String {
return "That is '$str' from C"
}
fun acceptFun(f: (String) -> String?) = f("Kotlin/Native rocks!")
fun supplyFun() : (String) -> String? = { "$it is cool!" }
- 更新
build.gradle(.kts)文件。以 Kotlin DSL 为例:
plugins {
kotlin("multiplatform") version "2.1.21"
}
repositories {
mavenCentral()
}
kotlin {
iosArm64("native") {
binaries {
framework {
baseName = "Demo"
}
}
}
}
tasks.wrapper {
gradleVersion = "8.10"
distributionType = Wrapper.DistributionType.ALL
}
binaries 块配置生成动态或共享库。Kotlin/Native 支持多种 Apple 目标平台,如 iosArm64、iosX64、iosSimulatorArm64、macosX64 和 macosArm64,可根据需要替换 Gradle 函数。
- 运行
linkDebugFrameworkNativeGradle 任务来构建 framework。使用命令./gradlew linkDebugFrameworkNative,生成的 framework 位于build/bin/native/debugFramework目录。也可以使用linkNative任务生成调试和发布变体。
生成的 Framework 头文件
每个 framework 变体都包含一个头文件,位于 build/bin/native/debugFramework/Demo.framework/Headers 目录中。头文件独立于目标平台,包含 Kotlin 代码的定义。
Kotlin/Native 运行时声明
头文件定义 Kotlin 运行时声明,例如 KotlinBase 基类(继承自 NSObject)以及集合和异常的包装器。集合类型映射到 Swift/Objective-C 中的相似类型:Kotlin List 映射到 Swift Array 和 Objective-C NSArray,MutableList 映射到 NSMutableArray,Set 映射到 Swift Set 和 Objective-C NSSet,MutableSet 映射到 NSMutableSet,Map 映射到 Swift Dictionary 和 Objective-C NSDictionary,MutableMap 映射到 NSMutableDictionary。
Kotlin 数值与 NSNumber
头文件包含 Kotlin/Native 数字类型与 NSNumber 的映射。基类在 Objective-C 中称为 DemoNumber,在 Swift 中称为 KotlinNumber,继承自 NSNumber。每个 Kotlin 数字类型都有对应的子类(如 KotlinByte、KotlinUByte 等),提供创建实例和提取值的方法。
Kotlin 中的类与对象
Kotlin 类、接口和对象映射到 Swift/Objective-C。例如,Interface 映射为 @protocol,Clazz 和 Object 映射为 @interface,并带有前缀如 Demo。可空返回值类型如 ULong? 转换为 DemoULong。
Kotlin 中的全局声明
所有全局函数转化为 Objective-C 中的 DemoLibKt 类和 Swift 中的 LibKt 类。Kotlin String 透明映射到 Objective-C NSString*,Unit 映射到 void。原生类型直接映射,可空原生类型映射到 Kotlin<TYPE>* 类型。高阶函数如 acceptFun 和 supplyFun 支持 Objective-C 块和 Swift 闭包。
垃圾回收与引用计数
Swift 和 Objective-C 使用自动引用计数(ARC),而 Kotlin/Native 有自己的垃圾回收器,并与 Swift/Objective-C ARC 集成。无需额外步骤管理 Kotlin/Native 实例的生命周期,未使用对象会自动清理。
在 Objective-C 中使用代码
在 Objective-C 中调用 framework,创建 main.m 文件示例:
#import <Foundation/Foundation.h>
#import <Demo/Demo.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
[DemoObject.shared field];
DemoClazz* clazz = [[ DemoClazz alloc] init];
[clazz memberP:42];
[DemoLibKt forIntegersB:1 s:1 i:3 l:[DemoULong numberWithUnsignedLongLong:4]];
[DemoLibKt forIntegersB:1 s:1 i:3 l:nil];
[DemoLibKt forFloatsF:2.71 d:[DemoDouble numberWithDouble:2.71]];
[DemoLibKt forFloatsF:2.71 d:nil];
NSString* ret = [DemoLibKt acceptFunF:^NSString * _Nullable(NSString * it) {
return [it stringByAppendingString:@" Kotlin is fun"];
}];
NSLog(@"%@", ret);
return 0;
}
}
Kotlin 对象通过 .shared 类属性访问单例,类实例使用 alloc 和 init 创建,全局函数作为 DemoLibKt 的类方法调用。
在 Swift 中使用代码
在 Swift 中使用 framework,创建 main.swift 文件示例:
import Foundation
import Demo
let kotlinObject = Object.shared
let field = Object.shared.field
let clazz = Clazz()
clazz.member(p: 42)
LibKt.forIntegers(b: 1, s: 2, i: 3, l: 4)
LibKt.forFloats(f: 2.71, d: nil)
let ret = LibKt.acceptFun { "\($0) Kotlin is fun" }
if (ret != nil) {
print(ret!)
}
Swift 中,Kotlin 对象通过 Object.shared 访问,函数和属性名称直接映射,类型如 String 透明转换,支持传递闭包。
将 framework 连接到 iOS 项目
生成的 framework 可以作为依赖添加到 iOS 项目中,有多种自动化方法可供选择,根据项目需求进行设置。
下一步做什么
- 了解更多关于与 Objective-C 的互操作性。
- 查看 Kotlin 中与 C 的互操作性实现。
- 参考 Kotlin/Native 作为动态库的教程。