Bas*_*ash 9 xcode ios kotlin watchos kotlin-multiplatform
在 Xcode 中使用 KMM 共享库时,在 Xcode 中构建时会出现多个警告
首先,让我解释一下我做了什么,以便更好地理解我所做的事情以及我在使用 Xcode 构建共享 KMM 库时遇到的一些问题。
我在我的 Windows PC 上使用 Android Studio 创建了一个 Android 项目,适用于手机、电视和穿戴设备,这三个设备都使用共享模块。我还想构建一个 iOS 应用程序,因此我在 Mac 上使用 Android Studio 创建一个新的 KMM 应用程序。我已将共享模块添加到此 KMM 应用程序并开始构建 iOS 应用程序。成功后,我添加了一个在 Apple Watch 上运行的应用程序,因此我使用 Xcode 手动添加一个适用于 iOS 应用程序的手表应用程序(文件 -> 新建 -> 目标...)。我配置了它,做了一些基本的编码/管道,构建了它,一切都工作正常。
共享模块稍作更改,使其与 Xcode 结合使用 Android,我已将其添加到Podfile(我也在我的项目中使用 Firebase):
target 'XYZ' do
use_frameworks!
platform :ios, '15.0'
pod 'shared', :path => '../shared'
# add pods for desired Firebase products
# https://firebase.google.com/docs/ios/setup#available-pods
pod 'Firebase/Messaging'
pod 'Firebase/Analytics'
pod 'Firebase/InAppMessaging'
end
target 'WatchXYZ' do
use_frameworks!
platform :watchos, '8.0'
pod 'shared', :path => '../shared'
# add pods for desired Firebase products
# https://firebase.google.com/docs/ios/setup#available-pods
pod 'Firebase/Messaging'
#pod 'Firebase/Analytics'
#pod 'Firebase/InAppMessaging'
end
target 'WatchXYZ WatchKit Extension' do
use_frameworks!
platform :watchos, '8.0'
pod 'shared', :path => '../shared'
# add pods for desired Firebase products
# https://firebase.google.com/docs/ios/setup#available-pods
pod 'Firebase/Messaging'
#pod 'Firebase/Analytics'
#pod 'Firebase/InAppMessaging'
end
Run Code Online (Sandbox Code Playgroud)
在共享的 src 目录中有四个子目录:androidMain、commonMain、iosMain 和 watchosMain。该目录中的内容build.gradle.kts如下所示:
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
id("com.android.library")
id("kotlin-parcelize")
kotlin("plugin.serialization") version "1.4.10"
}
version = "1.0"
kotlin {
android()
val iosTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget = when {
System.getenv("SDK_NAME")?.startsWith("iphoneos") == true -> ::iosArm64
System.getenv("NATIVE_ARCH")?.startsWith("arm") == true -> ::iosSimulatorArm64
else -> ::iosX64
}
iosTarget("ios") {}
watchos()
cocoapods {
summary = "Some description for the Shared Module"
homepage = "Link to the Shared Module homepage"
ios.deploymentTarget = "15.0"
watchos.deploymentTarget = "8.0"
framework {
baseName = "shared"
}
podfile = project.file("../iosApp/Podfile")
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
implementation("io.ktor:ktor-client-core:1.6.7")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting {
dependencies {
implementation("com.google.android.material:material:1.4.0")
implementation("io.ktor:ktor-client-android:1.6.7")
}
}
// Workaround for:
//
// The Kotlin source set androidAndroidTestRelease was configured but not added to any
// Kotlin compilation. You can add a source set to a target's compilation by connecting it
// with the compilation's default source set using 'dependsOn'.
// See https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#connecting-source-sets
//
// This workaround includes `dependsOn(androidAndroidTestRelease)` in the `androidTest` sourceSet.
val androidAndroidTestRelease by getting
val androidTest by getting {
dependsOn(androidAndroidTestRelease)
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.13.2")
}
}
val iosMain by getting {
dependencies {
//implementation("io.ktor:ktor-client-ios:1.6.7")
}
}
val iosTest by getting
val watchosMain by getting {
dependencies {
//implementation("io.ktor:ktor-client-ios:1.6.7")
}
}
val watchosTest by getting
}
}
android {
compileSdk = 30
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 28
targetSdk = 30
}
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
}
Run Code Online (Sandbox Code Playgroud)
虽然我使用旧版本的 Android Studio 创建了 KMM 应用程序,但当前版本是 Arctic Fox 2020.3.1 patch 4。使用 Xcode 13.2.1,我可以构建此项目,以便在装有 iOS 15.2 的 iPhone 7 设备上运行并运行它在模拟器中。Mac 是配备 macOS Monterey 12.1 的 iMac(Retina 5K,27 英寸,2015 年末)。我还没有 Apple Watch。
执行pod install和/或之类的命令pod update可以帮助我让共享库在 Xcode 中工作。一切都构建并运行良好,到目前为止没有任何问题。
当为设备、手机或手表模拟器构建时,我会收到一些警告。我想知道这些是否不好以及是否可以修复。
当为 iPhone 设备构建时,我收到 5100 多个警告,如下所示:
warning: (arm64) could not find object file symbol for symbol _kfun:io.ktor.utils.io.<get-EXPECTED_CAPACITY>#internal
和
warning: (arm64) could not find object file symbol for symbol _kfun:io.ktor.utils.io.ByteChannelSequentialBase#<get-writable>(){}io.ktor.utils.io.core.BytePacketBuilder
这里唯一要注意的是,在为 iOS 或 watchOS 模拟器构建时,我收到 2 个警告:
来自“XYZ”应用程序:
warning: (x86_64) could not find object file symbol for symbol __Konan_init_io.ktor:ktor-io-cinterop-sockets
来自“WatchXYZ WatchKit Extension”:
ld: warning: ignoring file /Users/bash/AndroidStudioProjects/XYZ/shared/build/cocoapods/framework/shared.framework/shared, building for watchOS Simulator-arm64 but attempting to link with file built for watchOS Simulator-x86_64
当我开始在 watchOS 应用程序中使用共享库时,只需使用共享库中的 Class1 实例实例化一个新变量,构建就会失败,并出现上述警告和错误:
Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_SharedClass1", referenced from:
objc-class-ref in XYZApp.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)
我尝试了以下操作: “XYZ”项目的
“构建设置”中的“仅构建活动架构”设置为“是”以进行发布(“调试”已设置为“是”)。此后 Xcode 的行为变得不可预测。重新启动并执行 iPhone 的构建命令后,我收到 4 个类似的错误。
错误(仅列出一种,其他类似):
Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_SharedClass1", referenced from:
objc-class-ref in MyView.o
Run Code Online (Sandbox Code Playgroud)
来回更改设置并执行另一个构建可以解决此错误。但重启后又恢复了。为了解决这个问题,我必须完全删除该设置。只有这样我才会回到第一个方向。
我的警告有多糟糕?这些可以以某种方式解决吗?该错误可能与警告有关。
===更新===
看来上面的组合非常让人难以捉摸。我尝试了很多不同的事情并花了我一段时间才弄清楚。经过多次后续构建请求后,相同的代码和相同的设置在 Xcode 中成功构建,并且可以在 iPhone 和 iWatch 上运行。我不知道为什么它一次后就不能正确构建。
这对我来说一直很好,直到上周最新的 Android Studio Bumblebee patch 1 更新。或者可能是由于 Android Gradle 或 Gradle 的更新,但似乎我又回到了原点。如果我按照以下步骤操作,我可以在 Xcode 中正确构建它并在实际的 iWatch 设备上运行该应用程序:
如果我需要对代码进行某些更改并希望再次重新运行代码,我必须重新从步骤 1 开始。如果我做了不同的事情,它就不会构建和运行。我不明白为什么它如此不可预测,为什么它多次失败却突然建立起来。我不会对设置或代码进行任何更改以使其构建或不构建。
如果有人可以向我解释为什么这是一种不可预测的行为……开发一些东西几乎是不可能的。
===更新===
安装 Android Studio Bumblebee 2021.1.1 Patch 2 后的另一个更新。现在看起来和以前一样工作。我仍然需要为 iPhone 3 进行编译,然后才能在 iWatch 上成功构建和运行。我可以再次更改代码并立即再次运行它,而无需执行之前更新中描述的整个过程。
似乎工作得“很好”。还有一些怪癖,但让我们看看我是否可以在不久的将来成功部署到 AppStore。
=====更新=====
我最终放弃了 Cocoapods,并将我的共享库链接为框架。在其他一些问题之后,这些问题都得到解决,一切正常。
我只在调试版本中收到“(arm64) 找不到目标文件符号”错误。经过一番折腾和咬牙切齿之后,到目前为止,我发现唯一对我有用的方法是强制 KMM 共享框架通过xcodeConfigurationToNativeBuildType映射构建并发布。
具体来说,在 build.gradle.kts 中的kotlin>下cocopods:
xcodeConfigurationToNativeBuildType["Debug"] =
org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType.RELEASE
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2531 次 |
| 最近记录: |