跳到主要内容
教程目录

Kotlin Multiplatform 在 Windows 上跑 iOS App 并断点调试 Kotlin

这篇带你在 Windows 上把 Kotlin Multiplatform 工程的 iOS 端装到 iPhone 上运行,在 VS Code 里同时给 Swift 和 Kotlin 打断点,最后打出能上传 App Store Connect 的 ipa。共享逻辑配 SwiftUI 界面、用 Compose Multiplatform 共享界面,两种工程都适用。你需要 Apple 开发者账号、一台 iPhone 和数据线,并且已经安装 KXBuild。

为什么 Windows 上编不了 iOS 端

KMP 的 iOS 端分两部分。共享的 Kotlin 代码由 Kotlin/Native 编成 iOS framework,iosApp 是一个普通的 Xcode 工程,构建时通过 Run Script 调 Gradle 生成这个 framework 并链接进 App。Kotlin 官方工具链只允许在 macOS 上编译 iOS 目标,iosApp 本身也要 Xcode 才能构建。

用 KXBuild 之后,iosApp 的构建、安装和调试交给 KXBuild,Gradle 脚本和 iosApp 工程都不用改。Android 端照旧在 Android Studio 里运行,两边共用同一份 Kotlin 代码。

准备开发环境

按 Kotlin Multiplatform 官网的说明安装 Android Studio,在「Settings → Plugins」里搜索并安装 Kotlin Multiplatform 插件。Android Studio 自带 JDK,Gradle 构建用它就够了。

共享的 Kotlin 代码照常在 Android Studio 里写,补全、重构、Android 端运行都在这里。VS Code 负责 iOS 端的构建、Swift 代码编辑和真机调试。

新建工程

已有工程在 VS Code 中「文件 → 打开文件夹」打开 KMP 工程根目录(settings.gradle.kts 所在的目录),或者把工程目录拖进 VS Code 即可。没有现成工程的,用 JetBrains 的向导新建。

  1. 打开 kmp.jetbrains.com,填好工程名和包名,勾选 Android 和 iOS。
  2. iOS 下面二选一。选「Share UI」得到 Compose Multiplatform 工程,界面也用 Kotlin 写。选「Do not share UI」得到共享逻辑、界面用 SwiftUI 的工程。
  3. 下载 zip,解压到 D:\work 这类短路径。

在 Android Studio 里用 New Project 选 Kotlin Multiplatform 模板也可以,同样要勾选 iOS。

生成的工程里,共享代码在 shared 或 composeApp 模块(取决于向导选项),iOS 端是 iosApp 目录下的 iosApp.xcodeproj。先在 Android Studio 里打开一次,等 Gradle 同步完成,确认 Android 端能跑,再到 VS Code 里打开工程根目录。KXBuild 视图会列出 iosApp 工程和它的 target。

体检

第一次打开工程必须先做这一步。 它会检查 Kotlin Multiplatform 环境,并准备好 iOS 端的工程。第一次运行要下载几百 MB,时间较长。以后升级了工程的 Kotlin 版本,要再运行一次。以下两种做法任选其一。

  • VS Code 插件。在 KXBuild 视图标题栏「···」中运行「体检并修复开发环境」。
  • 命令行。运行下面的命令。
1kxbuild doctor D:\work\mykmpapp\iosApp\iosApp.xcodeproj

配置 Bundle ID 和团队

向导生成的工程把 iOS 端的基本信息放在 iosApp\Configuration\Config.xcconfig,包括 TEAM_ID、BUNDLE_ID 和 App 名。TEAM_ID 填开发者账号的 Team ID,在 developer.apple.com 的 Membership 页能看到。BUNDLE_ID 改成你自己的域名反写,之后在开发者后台注册 App ID 用同一个。

改完后在 KXBuild 视图里右键 iosApp 这个 target,选择「KXBuild: 编辑目标设置」,在 General 页核对 Bundle Identifier 的最终值,它要和描述文件里的 App ID 一致。有的模板会把 Team ID 拼在 Bundle ID 后面,以这里显示的为准。工程设置编辑器的用法见工程设置编辑器。

签名用的证书和描述文件放进证书目录,开发阶段用 Apple Development 证书和包含这台 iPhone 的 Development 描述文件,做法见证书与签名。

编写共享代码和 iOS 界面

SwiftUI 界面调用 Kotlin

共享逻辑写在 commonMain 里,例如向导自带的 Greeting 类。

1class Greeting {
2    private val platform = getPlatform()
3
4    fun greet(): String = "Hello, ${platform.name}!"
5}

在 iosApp 的 Swift 代码里 import 共享模块生成的 framework,就能像调用 Swift 类一样调用它。framework 名在共享模块 build.gradle.kts 的 baseName 里,向导生成的 ContentView.swift 已经写好了 import。

1import SwiftUI
2import Shared
3
4struct ContentView: View {
5    var body: some View {
6        Text(Greeting().greet())
7    }
8}

Kotlin 的顶层函数在 Swift 里挂在「文件名 + Kt」的类上,比如 Platform.kt 里的函数通过 PlatformKt 调用。iosApp 下的 Swift 代码在 VS Code 里有补全、跳转和错误提示,Kotlin 新增的类和方法要构建一次之后 Swift 端才认得。

Compose Multiplatform 界面

选了「Share UI」的工程,界面写在 commonMain 的 App() 这个 Composable 里,iosMain 里的 MainViewController() 把它包成 UIViewController,iosApp 的 ContentView.swift 再把它放进 SwiftUI。这三处向导都生成好了,日常只改 commonMain 里的 Compose 代码。

需要调用 iOS 专有的 API 时,在 commonMain 里声明 expect,在 iosMain 里写 actual 实现,iosMain 可以直接使用 UIKit、Foundation 这些 iOS 框架。

在 iPhone 上运行

用数据线连上 iPhone。第一次连接要安装 Apple 设备驱动、在手机上点「信任此电脑」、打开开发者模式,做法见设备准备。然后在 KXBuild 视图的「设备」节点下点一下这台 iPhone,选为当前设备,按 F5。

KXBuild 会依次构建、签名、安装、启动 App 并接上调试器。构建时会自动调 Gradle 编译 Kotlin 代码,第一次还要下载 Gradle 依赖,耗时比较长,之后只编改过的部分。第一次调试某个 iOS 版本时会自动下载符号库,有几个 GB,只需要一次,进度显示在通知里。

App 的输出在「输出 → KXBuild Console」,Kotlin 里 println 的内容也在这里。构建日志在「输出 → KXBuild」,Gradle 报错时从这里看完整输出。

同时调试 Swift 和 Kotlin

Kotlin 源文件在 VS Code 里直接打开,比如 shared\src\commonMain\kotlin\...\Greeting.kt,在行号左侧点一下就能打断点。Swift 文件也一样,两边的断点在同一次调试里都生效。

VS Code 中 Windows 上真机调试 iOS App

  • 停在 Kotlin 断点时,变量视图里的 Kotlin 对象按类和字段展开,调用栈能看到从 Swift 到 Kotlin 的完整调用链。
  • 停在 Swift 里调用 Kotlin 的那一行时,用「单步进入」可以直接进到 Kotlin 函数里。
  • commonMain 和 iosMain 的代码都能打断点,Compose 的 Composable 函数和点击回调也可以。
  • 调试控制台可以输入 lldb 命令,Kotlin 的值在变量视图里查看。

断点位置对不上或者停在汇编上,先确认「构建配置」节点选的是 Debug。Release 配置经过优化,不适合断点调试。

改代码之后怎么更新

Kotlin 和 Swift 代码改完,停止调试后重新按 F5。构建会自动重新编译 Kotlin framework 并装到手机上,不需要先在 Android Studio 里手动跑 Gradle 任务。调试工具栏上的「重启」不会重新编译,改了代码要用 F5。

改了 build.gradle.kts 里的依赖,也是直接按 F5,Gradle 会在构建时下载新依赖。升级了 Kotlin 或 Compose Multiplatform 版本,先重新运行一次体检再构建。

打包 Release ipa

上架前先改版本号。在工程设置编辑器的 General 页修改 Marketing Version(商店里显示的版本)和 Current Project Version(构建号),每次上传 App Store Connect,构建号都要比上一次大。证书目录里要有 Apple Distribution 证书和 App Store 类型的描述文件。以下两种做法任选其一。

  • VS Code 插件。在 KXBuild 视图的「构建配置」节点切到 Release,命令面板运行 KXBuild: 构建。
  • 命令行。在工程根目录运行下面的命令。
1kxbuild build .\iosApp\iosApp.xcodeproj -c Release

Release 构建会用 Release 模式编译 Kotlin,时间比 Debug 长。完成后在 iosApp\build 下得到以 App 名命名的 .ipa。在 Windows 上用 Appuploader 上传到 App Store Connect,处理完成后在 TestFlight 里装到手机上验证,再提交审核,详见发布与上架。

常见问题

构建在 Run Script 阶段报 Gradle 错误

在「输出 → KXBuild」里找 Gradle 的第一条错误。刚拉下工程或刚升级 Kotlin 版本的,重新运行一次体检。确认工程在 Android Studio 里能正常同步,Gradle 本身的错误在两边是一样的。

Swift 里找不到 Kotlin 新加的类或方法

Swift 看到的是上一次构建生成的 framework。按一次 F5 或「KXBuild: 构建」,之后补全和错误提示就会更新。只在 Android 或其他平台的源码集里声明的代码,iOS 端看不到,要放在 commonMain 或 iosMain。

Compose 工程安装后一启动就退出

先看「输出 → KXBuild Console」里的报错。Compose Multiplatform 要求 Info.plist 里有 CADisableMinimumFrameDurationOnPhone 并设为 YES,向导生成的 Info.plist 里有这一项,删掉或换了 Info.plist 时会启动即退出。用属性列表编辑器打开 iosApp\iosApp\Info.plist 加回来即可。

安装时报描述文件不匹配

Bundle Identifier 和描述文件里的 App ID 不一致,常见于 Bundle ID 后面被拼上了 Team ID。按配置 Bundle ID 和团队核对最终值。其他签名报错见签名与安装报错。

其他错误见排错与 FAQ。