Tuesday, September 27, 2022
HomeiOS Developmentios - Uncaught Kotlin exception: kotlin.native.IncorrectDereferenceException: unlawful try to entry non-shared @20d9a28...

ios – Uncaught Kotlin exception: kotlin.native.IncorrectDereferenceException: unlawful try to entry non-shared @20d9a28 from different thread


I am writing an app for each Android and iOS, now I want to extract some components to a Kotlin Multiplatform library.

The Android half works as anticipated, however when calling the API from iOS, I get

Uncaught Kotlin exception: kotlin.native.IncorrectDereferenceException: unlawful try to entry non-shared <object>@20d9a28 from different thread

My setup:
construct.gradle.kts within the shared module:

import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework

plugins {
    kotlin("multiplatform")
    id("com.android.library")
    id("kotlin-android-extensions")
    kotlin("plugin.serialization")
}

repositories {
    gradlePluginPortal()
    google()
    jcenter()
    mavenCentral()
    maven {
        url = uri("https://dl.bintray.com/kotlin/kotlin-eap")
    }
}

kotlin {
    android()

    val frameworkBaseName = "MySharedCode"
    val xcframework = XCFramework(frameworkBaseName)

    // ios() contains x86 sim & arm64 gadget
    ios {
        binaries.framework {
            baseName = frameworkBaseName
            xcframework.add(this)
        }
    }
    // iosSimulatorArm64() provides Apple Silicon simulator assist
    iosSimulatorArm64 {
        binaries.framework {
            baseName = frameworkBaseName
            xcframework.add(this)
        }
    }

    sourceSets {
// 1
        val commonMain by getting {
            dependencies {
                implementation("co.touchlab:stately-common:1.2.0")
                implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
                implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.3.3")
                implementation("io.ktor:ktor-client-core:2.1.1")
                implementation("io.ktor:ktor-client-auth:2.1.1")
                implementation("io.ktor:ktor-client-logging:2.1.1")
                implementation("io.ktor:ktor-client-content-negotiation:2.1.1")
                implementation("io.ktor:ktor-client-core:2.1.1")
                implementation("io.ktor:ktor-client-serialization:2.1.1")
                implementation("io.ktor:ktor-serialization-kotlinx-json:2.1.1")
                implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3")
                implementation("com.liftric:kvault:1.9.0")
            }
        }
// 2
        val androidMain by getting {
            dependencies {
                implementation("io.ktor:ktor-client-okhttp:2.1.1")
                implementation("androidx.safety:security-crypto:1.0.0")
                implementation("io.ktor:ktor-client-android:2.1.1")
            }
        }
        val androidTest by getting
        val iosX64Main by getting
        val iosArm64Main by getting
        val iosSimulatorArm64Main by getting
//        val androidAndroidTestRelease by getting
        val iosMain by getting {
            dependsOn(commonMain)
            iosX64Main.dependsOn(this)
            iosArm64Main.dependsOn(this)
            iosSimulatorArm64Main.dependsOn(this)
            dependencies {
                implementation("io.ktor:ktor-client-ios:2.1.1")
                implementation("io.ktor:ktor-client-darwin:2.1.1")
            }
        }
        val iosX64Test by getting
        val iosArm64Test by getting
        val iosSimulatorArm64Test by getting
        val commonTest by getting {
            dependencies {
                implementation(kotlin("take a look at"))
            }
        }
        val iosTest by getting {
            dependsOn(commonTest)
            iosX64Test.dependsOn(this)
            iosArm64Test.dependsOn(this)
            iosSimulatorArm64Test.dependsOn(this)
        }
    }
}

android {
    compileSdk = 32
    sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
    defaultConfig {
        minSdk = 26
        targetSdk = 32
    }
}

I create the xcframework through the duty assembleMySharedCodeXCFramework. Then I exploit that through SPM in my iOS app.

My Android code in commonMain:

val httpClient by lazy {
    HttpClient {
        expectSuccess = true
        set up(ContentNegotiation) {
            json(Json {
                ignoreUnknownKeys = true
                prettyPrint = true
                isLenient = true
            })
        }
    }
}

class DogApiImpl() {

    init {
        ensureNeverFrozen()
    }

    droop enjoyable makeTheCall(): BreedResult {
        return httpClient.get("https://canine.ceo/api/breeds/checklist/all").physique<BreedResult>()
    }
}

The decision in my iOS app:

DispatchQueue.primary.async {
    DogApiImpl().makeTheCall { outcome, error in
        debugPrint(outcome, error)
    }
}

What am I lacking right here? :/

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments