Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/207.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何在iOS项目上添加两个或多个kotlin本机模块 TL;博士_Android_Ios_Kotlin_Gradle_Kotlin Multiplatform - Fatal编程技术网

Android 如何在iOS项目上添加两个或多个kotlin本机模块 TL;博士

Android 如何在iOS项目上添加两个或多个kotlin本机模块 TL;博士,android,ios,kotlin,gradle,kotlin-multiplatform,Android,Ios,Kotlin,Gradle,Kotlin Multiplatform,如何在一个iOS项目上添加两个或多个kotlin本机模块,而不获取重复符号 详细问题 下面我们假设一个多模块KMP项目,其中存在一个用于Android的本机应用程序和一个用于iOS的本机应用程序,以及两个用于保存共享kotlin代码的通用模块 。 ├── 安卓 │ └── 应用程序 ├── 常见的 │ ├── 模 │ └── 模B ├── 网间网操作系统 │ └── 应用程序 模块A包含一个数据类HelloWorld,并且没有模块依赖项: 包hello.world.module

如何在一个iOS项目上添加两个或多个kotlin本机模块,而不获取重复符号

详细问题 下面我们假设一个多模块KMP项目,其中存在一个用于Android的本机应用程序和一个用于iOS的本机应用程序,以及两个用于保存共享kotlin代码的通用模块

。
├── 安卓
│   └── 应用程序
├── 常见的
│   ├── 模
│   └── 模B
├── 网间网操作系统
│   └── 应用程序
模块A包含一个数据类HelloWorld,并且没有模块依赖项:

包hello.world.modulea
数据类HelloWorld(
val消息:字符串
)
模块B包含HelloWorld类的扩展函数,因此它依赖于模块A:

包hello.world.moduleb
导入hello.world.modulea.HelloWorld
fun HelloWorld.egassem()=message.reversed()
模块的build.gradle配置为:

  • 模块A
  • 模块B
它看起来非常简单,如果我将android build gradle依赖项配置为以下内容,它甚至可以在android上运行:

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72"
    implementation project(":common:moduleA")
    implementation project(":common:moduleB")
}
但是,这似乎不是在iOS上组织多个模块的正确方法,因为运行
/gradlew podspec
我可以获得
构建成功
,正如预期的那样,使用以下pod:

pod'moduleA',:path=>'…/HelloWorld/common/moduleA'
pod'moduleB',:path=>'…/HelloWorld/common/moduleB'
即使运行
pod安装
我也能成功地完成
pod安装!Podfile中有2个依赖项,总共安装了2个POD。
Xcode在pods部分显示模块A和模块B后,什么看起来正确

但是,如果我尝试构建iOS项目,会出现以下错误:

Ld…/Hello\u World-…/Build/Products/Debug iphonesimulator/Hello\World.app/Hello\World normal x86\u 64(在项目“Hello World”的目标“Hello World”中)
cd…/HelloWorld/ios/app
…
在以下位置重复符号“\u ktypew:kotlin.Any”:
…/HelloWorld/common/moduleA/build/cocoapods/framework/moduleA.framework/moduleA(result.o)
…/HelloWorld/common/moduleB/build/cocoapods/framework/moduleB.framework/moduleB(result.o)
…大量重复符号更多…
重复符号“\u kfun:kotlin.throwon失败$stdlib@kotlin.Result.()在:
…/HelloWorld/common/moduleA/build/cocoapods/framework/moduleA.framework/moduleA(result.o)
…/HelloWorld/common/moduleB/build/cocoapods/framework/moduleB.framework/moduleB(result.o)
ld:9928体系结构x86_64的重复符号
叮当声:错误:链接器命令失败,退出代码为1(使用-v查看调用)
我对iOS的了解不多,所以在我未经训练的眼中,似乎每个模块都在添加自己版本的东西,而不是使用一些分辨率策略来共享

如果我只使用模块A,代码可以正常工作和运行,因此我知道代码本身是正确的,问题是如何管理多个模块,因此问题是,如何在iOS上同时添加(模块A和模块B)并使其正常工作

附笔
我确实尽可能地减少了代码,试图只保留我认为是问题根源的部分,但是,如果您想检查代码片段中缺少的任何内容,或者如果您想运行并尝试解决问题,则可以使用完整的代码…

多个Kotlin框架可能很棘手,但是应该在1.3.70开始工作,我看到你有

问题似乎是这两个框架都是静态的,这在1.3.70中是一个问题,所以它不起作用。(应在1.40之前进行更新)。默认情况下,cocoapods插件会将框架设置为静态的,这是不起作用的。我不知道有什么方法可以将cocoapods设置为动态的,但是我已经测试过不使用cocoapods的构建,并在gradle任务中使用
isStatic
变量,并且已经得到了一个iOS项目来编译。比如:

binaries {
    framework("moduleA"){
        isStatic = false
    }
}
现在,您可以通过使用上面的代码并创建一个任务来构建框架()来使用此方法解决这个问题

另一件值得注意的事情是,在iOS端,HelloWorld类将显示为两个独立的类,尽管它们都来自moduleA。对于多个Kotlin框架,这是另一种奇怪的情况,但我认为扩展在这种情况下仍然可以工作,因为您返回了一个字符串

实际上,我刚刚写了一篇关于多个Kotlin框架的博文,如果您想看一看的话,这可能有助于解决一些其他问题

EDIT:看起来
cocoapodsext
也有一个
isStatic
变量,因此将其设置为
isStatic=false

tl:dr在同一个iOS项目中,当前不能有多个静态Kotlin框架。使用
isStatic=false
将它们设置为非静态

但是,如果我尝试构建iOS项目,会出现以下错误:

此特定错误是已知的问题。多个调试静态框架与编译器缓存不兼容

因此,要解决这个问题,您可以通过在
gradle.properties
中插入以下行来禁用编译器缓存:

kotlin.native.cacheKind=none
或者,通过向Gradle构建脚本中添加以下代码片段,使框架成为动态的:

kotlin{
目标.withType{
binaries.withType{
isStatic=false
}
}
}
有关更多详细信息,请参阅

我猜当前多框架的行为对于最初的主题初学者来说没有多大意义,我只是在这里为可能遇到相同问题的任何人提供答案

我对iOS的了解不多,所以在我未经训练的眼中,似乎每个模块都在添加自己版本的东西,而不是使用一些分辨率策略来共享

这正是它在这个mo中的工作方式
binaries {
    framework("moduleA"){
        isStatic = false
    }
}
kotlin.native.cacheKind=none