Ktor依赖未在多平台项目的iOS模块中解决

6

我有一个针对iOS和Android的kotlin-multiplatform项目。 在common模块中使用了Ktor http客户端。

Android应用程序一切正常。 但是在构建iOS库时,我收到以下异常:

> Task :app:compileKotlinIos FAILED
src/commonMain/kotlin/com/ottamotta/mozoli/api/MozoliApiKtor.kt:4:8: error: unresolved reference: io
import io.ktor.client.HttpClient
       ^
src/commonMain/kotlin/com/ottamotta/mozoli/api/MozoliApiKtor.kt:5:8: error: unresolved reference: io
import io.ktor.client.features.feature

......和其他一些错误提示,指出ktot依赖项没有被解析。

以下是build.gradle文件:

plugins {
    id 'kotlin-multiplatform' version '1.3.10'
}
repositories {
    google()
    jcenter()
    mavenCentral()
    maven { url "https://kotlin.bintray.com/kotlinx" }
}

ext {
    support_lib_version = '28.0.0'
    ktor_version = '1.0.0'
}

def keystorePropertiesFile = rootProject.file("./app/secret.properties");
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    buildToolsVersion '28.0.3'
    defaultConfig {
        applicationId "com.ottamotta.mozoli"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        manifestPlaceholders = [auth0Domain: "@string/com_auth0_domain", auth0Scheme: "https"]
    }
    buildTypes {

        debug {
            resValue "string", "com_auth0_client_id", keystoreProperties['com_auth0_client_id']
        }
        release {
            resValue "string", "com_auth0_client_id", keystoreProperties['com_auth0_client_id']
            minifyEnabled false
        }
    }

    lintOptions {
        abortOnError false
    }


}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "com.android.support:recyclerview-v7:${support_lib_version}"
    implementation "com.android.support:appcompat-v7:${support_lib_version}"
    implementation 'com.squareup.picasso:picasso:2.71828'

    implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.9.7"

    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1")
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'

    implementation "com.auth0.android:auth0:1.14.1"

    androidTestImplementation 'com.android.support.test:runner:1.0.2'
}

kotlin {
    targets {
        fromPreset(presets.android, 'android')
        // This preset is for iPhone emulator
        // Switch here to presets.iosArm64 (or iosArm32) to build library for iPhone device
        fromPreset(presets.iosX64, 'ios') {
            compilations.main.outputKinds('FRAMEWORK')
        }
    }
    sourceSets {
        commonMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
                implementation "io.ktor:ktor-client:$ktor_version"
                implementation "io.ktor:ktor-client-json:$ktor_version"
                implementation "io.ktor:ktor-client-jackson:$ktor_version"
            }
        }
        commonTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test-common'
                implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
            }
        }
        androidMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib'
                implementation "io.ktor:ktor-client-android:$ktor_version"
            }
        }
        androidTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test'
                implementation 'org.jetbrains.kotlin:kotlin-test-junit'
            }
        }
        iosMain {
            dependencies {
                implementation("io.ktor:ktor-client-ios:$ktor_version")
            }
        }
        iosTest {
        }
    }
}

task copyFramework {
    def buildType = project.findProperty("kotlin.build.type") ?: "DEBUG"
    def target = project.findProperty("kotlin.target") ?: "ios"
    dependsOn "link${buildType.toLowerCase().capitalize()}Framework${target.capitalize()}"

    doLast {
        def srcFile = kotlin.targets."$target".compilations.main.getBinary("FRAMEWORK", buildType)
        def targetDir = getProperty("configuration.build.dir")
        copy {
            from srcFile.parent
            into targetDir
            include 'app.framework/**'
            include 'app.framework.dSYM'
        }
    }
}

这是来自 common 模块的文件代码,会产生错误:

package com.ottamotta.mozoli.api

import com.ottamotta.mozoli.*
import io.ktor.client.HttpClient
import io.ktor.client.features.feature
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.JsonSerializer
import io.ktor.client.features.json.defaultSerializer
import io.ktor.client.request.header
import io.ktor.client.request.request
import io.ktor.client.request.url
import io.ktor.http.HttpMethod


class MozoliApiKtor(
    private val serverUrl: String,
    private var jsonSerializer: JsonSerializer? = null,
    private val tokenProvider: suspend () -> String?
) : MozoliApi {

    private val client: HttpClient

    private val AUTH_HEADER = "Authorization";
    private val TOKEN_PREFIX = "Bearer "

    init {
        client = HttpClient {
            install(JsonFeature) {
                serializer = jsonSerializer ?: defaultSerializer()
            }
        }
        jsonSerializer = client.feature(JsonFeature)?.serializer
    }

    override suspend fun getUserProfile(): User {
        return client.request {
            url("${serverUrl}/user/")
            method = HttpMethod.Get
            header(AUTH_HEADER, TOKEN_PREFIX + tokenProvider())
        }
    }

    override suspend infix fun getEventsByCity(cityId: String): List<Event> {
        return client.request {
                url("${serverUrl}/event/city/${cityId}")
                method = HttpMethod.Get
                header(AUTH_HEADER, TOKEN_PREFIX + tokenProvider())
            }

    }

}

似乎传递依赖项无法解析。 你可以尝试显式添加以下代码:implementation "io.ktor:ktor-client-core-ios:$ktor_version" - Leonid
感谢@Leonid的回复,不幸的是,使用以下依赖项在build.gradle中仍然存在相同的错误:iosMain { dependencies { implementation ("io.ktor:ktor-client-core-ios:$ktor_version") implementation ("io.ktor:ktor-client-ios:$ktor_version") } } - Rodion Altshuler
顺便说一句,没有常见的Jackson功能。 - Leonid
你能试一下这个配置吗:https://github.com/JetBrains/kotlinconf-app/blob/master/common/build.gradle? - Leonid
2个回答

10
我遇到了和你完全一样的问题。Android应用程序已经构建并且可以无缺陷地运行,但是iOS模块无法找到任何Ktor、coroutine或kotlinx序列化类。
按照https://github.com/adrianbukros/github-multiplatform-example的步骤,并尝试复制他们的设置,我最终通过复制他们的gradle设置中的一些部分,使packForXCode任务得以工作。
他们的公共模块build.gradle应该如下所示:
apply plugin: 'kotlin-multiplatform'
apply plugin: 'kotlinx-serialization'

kotlin {
    targets {
        fromPreset(presets.jvm, "android")

        fromPreset(presets.iosX64, "ios_x86_64")
        fromPreset(presets.iosArm64, "ios_arm64")
        configure([ios_x86_64, ios_arm64]) {
            compilations.main.outputKinds("FRAMEWORK")
        }
    }

    sourceSets {
        commonMain.dependencies {
            implementation "org.jetbrains.kotlin:kotlin-stdlib"
            implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version"
            implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"

            implementation "io.ktor:ktor-client-core:$ktor_version"
            implementation "io.ktor:ktor-client-json:$ktor_version"
        }

        androidMain.dependencies {
            implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
            implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"

            implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"

            implementation "io.ktor:ktor-client-core-jvm:$ktor_version"
            implementation "io.ktor:ktor-client-json-jvm:$ktor_version"
        }

        iosMain.dependencies {
            implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version"
            implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version"

            implementation "io.ktor:ktor-client-ios:$ktor_version"
            implementation "io.ktor:ktor-client-core-ios:$ktor_version"
            implementation "io.ktor:ktor-client-json-ios:$ktor_version"
        }
        configure([ios_x86_64Main, ios_arm64Main]) {
            dependsOn iosMain
        }
    }
}

// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
    compileClasspath
}

task packForXCode(type: Sync) {
    final File frameworkDir = new File(buildDir, "xcode-frameworks")

    final String configuration = project.findProperty("CONFIGURATION")?.toUpperCase() ?: "DEBUG"
    final String arch = project.findProperty("ARCHS") ?: "x86_64"

    dependsOn kotlin.targets."ios_${arch}".compilations.main.linkTaskName("FRAMEWORK", configuration)

    from { kotlin.targets."ios_${arch}".compilations.main.getBinary("FRAMEWORK", configuration).parentFile }
    into frameworkDir
}

tasks.build.dependsOn packForXCode

他们的settings.gradle文件应该长这样:

enableFeaturePreview("GRADLE_METADATA") // IMPORTANT!

include 'commoncode'
include 'app'

如果仍然无法正常工作,请查看他们所有的*.gradlegradle.*文件,看看你的文件与他们有何不同。
这最终使任务通过了,我可以在XCode中使用我的Kotlin Ktor代码。但是,现在Android Studio表示共享的iOS模块未配置Kotlin。如果我找到原因,我会回报的,如果您发现了什么,请分享!
编辑 将公共模块的build.gradle更改为以下内容,似乎一切都很顺利!
apply plugin: 'kotlin-multiplatform'
apply plugin: 'kotlinx-serialization'

kotlin {
    targets {
        fromPreset(presets.jvm, 'android')

        // Change to `presets.iosArm64` to deploy the app to iPhone
        fromPreset(presets.iosX64, 'ios') {
            compilations.main.outputKinds('FRAMEWORK')
        }
    }

    sourceSets {
        commonMain.dependencies {
            implementation "org.jetbrains.kotlin:kotlin-stdlib"
            implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version"
            implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"

            implementation "io.ktor:ktor-client-core:$ktor_version"
            implementation "io.ktor:ktor-client-json:$ktor_version"
        }

        androidMain.dependencies {
            implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
            implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"

            implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"

            implementation "io.ktor:ktor-client-core-jvm:$ktor_version"
            implementation "io.ktor:ktor-client-json-jvm:$ktor_version"
        }

        iosMain.dependencies {
            implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version"
            implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version"

            implementation "io.ktor:ktor-client-ios:$ktor_version"
            implementation "io.ktor:ktor-client-core-ios:$ktor_version"
            implementation "io.ktor:ktor-client-json-ios:$ktor_version"
        }
    }
}

// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
    compileClasspath
}

task packForXCode(type: Sync) {
    final File frameworkDir = new File(buildDir, "xcode-frameworks")
    final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'

    inputs.property "mode", mode
    dependsOn kotlin.targets.ios.compilations.main.linkTaskName("FRAMEWORK", mode)

    from { kotlin.targets.ios.compilations.main.getBinary("FRAMEWORK", mode).parentFile }
    into frameworkDir

    doLast {
        new File(frameworkDir, 'gradlew').with {
            text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n"
            setExecutable(true)
        }
    }
}

tasks.build.dependsOn packForXCode

3
谢谢! enableFeaturePreview("GRADLE_METADATA") 让它对我起作用。 - krlbsk
是的,我也一样。enableFeaturePreview("GRADLE_METADATA") 这个命令让我的工作正常了。 - Arjun Kalidas
enableFeaturePreview("GRADLE_METADATA") 让我也能够构建。 - Danuofr

0

目前,Kotlin 多平台在 Windows 上无法运行 iOS 版本。这就解释了为什么您的 iosmain 代码中只有依赖项无法解析。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接