Thread
#multiplatform
    Michael Pohl

    Michael Pohl

    1 year ago
    Hi everyone! Maybe someone can help me out with what are probably Multiplatform beginner questions... I just went through the Kotlin Multiplatform Hands-on: Networking and Data Storage tutorial. the Android build is running, but iOS crashes at startup. I've been double and triple checking everything but I cannot find anything I did wrong. Tbh, I also have trouble understanding what the stacktrace tells me (as in: Which of the mentioned classes in there is the origin of the problem):
    Function doesn't have or inherit @Throws annotation and thus exception isn't propagated from Kotlin to Objective-C/Swift as NSError.
    It is considered unexpected and unhandled instead. Program will be terminated.
    Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlinx.coroutines.ChildHandleNode@12e2608
        at 0   shared                              0x0000000104b05f7d kfun:kotlin.Throwable#<init>(kotlin.String?){} + 93 (/Users/teamcity/buildAgent/work/cae0e6559deed4c4/runtime/src/main/kotlin/kotlin/Throwable.kt:23:37)
        at 1   shared                              0x0000000104afeb2b kfun:kotlin.Exception#<init>(kotlin.String?){} + 91 (/Users/teamcity/buildAgent/work/cae0e6559deed4c4/runtime/src/main/kotlin/kotlin/Exceptions.kt:23:44)
        at 2   shared                              0x0000000104afed7b kfun:kotlin.RuntimeException#<init>(kotlin.String?){} + 91 (/Users/teamcity/buildAgent/work/cae0e6559deed4c4/runtime/src/main/kotlin/kotlin/Exceptions.kt:34:44)
        at 3   shared                              0x0000000104b3520b kfun:kotlin.native.concurrent.InvalidMutabilityException#<init>(kotlin.String){} + 91 (/Users/teamcity/buildAgent/work/cae0e6559deed4c4/runtime/src/main/kotlin/kotlin/native/concurrent/Freezing.kt:22:60)
        at 4   shared                              0x0000000104b356e2 ThrowInvalidMutabilityException + 690 (/Users/teamcity/buildAgent/work/cae0e6559deed4c4/runtime/src/main/kotlin/kotlin/native/concurrent/Internal.kt:92:11)
        at 5   shared                              0x0000000104c2958c MutationCheck + 108
        at 6   shared                              0x0000000104d167b6 kfun:kotlinx.coroutines.internal.LinkedListNode#<set-_next>(kotlinx.coroutines.internal.LinkedListNode){} + 102 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/internal/LinkedList.kt:19:28)
        at 7   shared                              0x0000000104d16b3b kfun:kotlinx.coroutines.internal.LinkedListNode#addLast(kotlinx.coroutines.internal.LinkedListNode){} + 283 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/internal/LinkedList.kt:31:9)
        at 8   shared                              0x0000000104d16e86 kfun:kotlinx.coroutines.internal.LinkedListNode#addOneIfEmpty(kotlinx.coroutines.internal.LinkedListNode){}kotlin.Boolean + 230 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/native/src/internal/LinkedList.kt:47:9)
        at 9   shared                              0x0000000104cc6ecf kfun:kotlinx.coroutines.JobSupport.promoteSingleToNodeList#internal + 463 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/JobSupport.kt:532:15)
        at 10  shared                              0x0000000104cc5b2d kfun:kotlinx.coroutines.JobSupport#invokeOnCompletion(kotlin.Boolean;kotlin.Boolean;kotlin.Function1<kotlin.Throwable?,kotlin.Unit>){}kotlinx.coroutines.DisposableHandle + 2061 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/JobSupport.kt:470:25)
        at 11  shared                              0x0000000104cc529f kfun:kotlinx.coroutines.JobSupport#invokeOnCompletion(kotlin.Function1<kotlin.Throwable?,kotlin.Unit>){}kotlinx.coroutines.DisposableHandle + 207 (/opt/buildAgent/work/44ec6e850d5c63f0/kotlinx-coroutines-core/common/src/JobSupport.kt:449:9)
        at 12  shared                              0x0000000104e62d14 kfun:io.ktor.client#HttpClient(io.ktor.client.engine.HttpClientEngineFactory<0:0>;kotlin.Function1<io.ktor.client.HttpClientConfig<0:0>,kotlin.Unit>){0§<io.ktor.client.engine.HttpClientEngineConfig>}io.ktor.client.HttpClient + 1156 (/opt/buildAgent/work/a85294440dc5c6e/ktor-client/ktor-client-core/common/src/io/ktor/client/HttpClient.kt:45:36)
        at 13  shared                              0x0000000104ea5d0e kfun:io.ktor.client#HttpClient(kotlin.Function1<io.ktor.client.HttpClientConfig<*>,kotlin.Unit>){}io.ktor.client.HttpClient + 638 (/opt/buildAgent/work/a85294440dc5c6e/ktor-client/ktor-client-core/posix/src/io/ktor/client/HttpClient.kt:18:46)
        at 14  shared                              0x0000000104a7ad67 kfun:com.example.multiplatformtest.shared.network.SpaceXApi#<init>(){} + 199
        at 15  shared                              0x0000000104a6e6a7 kfun:com.example.multiplatformtest.shared.SpaceXSDK#<init>(com.example.multiplatformtest.shared.cache.DatabaseDriverFactory){} + 327
        at 16  shared                              0x0000000104a7f6a8 objc2kotlin.12 + 232
        at 17  iosApp                              0x000000010497e9f7 $sSo15SharedSpaceXSDKC21databaseDriverFactoryABSo0a8DatabaseeF0C_tcfC + 39
        at 18  iosApp                              0x000000010497f4cb $s6iosApp13SceneDelegateCACycfc + 219 (/Users/michaelpohl/Development/Misc/MultiplatformTest/iosApp/iosApp/SceneDelegate.swift:5:0)
        at 19  iosApp                              0x000000010497f573 $s6iosApp13SceneDelegateCACycfcTo + 19
        at 20  UIKitCore                           0x000000010ecde71d -[UIScene initWithSession:connectionOptions:] + 709
        at 21  UIKitCore                           0x000000010fb0976b -[UIWindowScene initWithSession:connectionOptions:] + 88
        at 22  UIKitCore                           0x000000010ece1f12 +[UIScene _sceneForFBSScene:create:withSession:connectionOptions:] + 627
        at 23  UIKitCore                           0x000000010f88142b -[UIApplication _connectUISceneFromFBSScene:transitionContext:] + 1114
        at 24  UIKitCore                           0x000000010f88175a -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 289
        at 25  UIKitCore                           0x000000010f370c27 -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 358
        at 26  FrontBoardServices                  0x0000000115d3a146 -[FBSScene _callOutQueue_agent_didCreateWithTransitionContext:completion:] + 391
        at 27  FrontBoardServices                  0x0000000115d62c0d __94-[FBSWorkspaceScenesClient createWithSceneID:groupID:parameters:transitionContext:completion:]_block_invoke.176 + 102
        at 28  FrontBoardServices                  0x0000000115d47ba1 -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 209
        at 29  FrontBoardServices                  0x0000000115d628db __94-[FBSWorkspaceScenesClient createWithSceneID:groupID:parameters:transitionContext:completion:]_block_invoke + 352
    I understand that I need the @Throws annotation for iOS to understand Exceptions, but where am I missing any? If I got right what I've built going through the tutorial there is
    SpaceXSDK
    as the single point of entry to the shared module, which one function is correctly anntoated. I was unable to find a guide to debugging such problems properly, is there a good resource on this? Other things I noticed: The
    DatabaseDriverFactory
    in the iOS package shows
    com.squareup.sqldelight.drivers
    as an unresolved reference, but it looks like that's an IDE error? Same about the
    AppDataBase.kt
    generated by SqolDelight. It exists in the build folder, and since at least the Android side compiles just fine, I assume it works correctly. Just wondering if that can also be generated into the actual source, so that I don't have n IDE error...? any insights are much appreciated!
    oh ,if anyone is interested, here's a link to my code (it's just what I built following the tutorial):
    Samuel Michael

    Samuel Michael

    1 year ago
    @Throws(Exception::class) suspend fun getLaunches(forceReload: Boolean): List<RocketLaunch> { val cachedLaunches = database.getAllLaunches() return if (cachedLaunches.isNotEmpty() && !forceReload) { cachedLaunches } else { api.getAllLaunches().also { database.clearDatabase() database.createLaunches(it) } } }
    Slide in BuildingSDK page of tutorial
    Nevermind that sounds like more of a concurrency/thread issue, see you have the correct annotation I mentioned above
    Michael Pohl

    Michael Pohl

    1 year ago
    yes I do. I am actually wondering if this might be caused by any of the libraries, given that this is all fast-moving and very alpha. But I haven't fully grasped Mutliplatform yet, so I'm a little lost atm.
    s

    Sam

    1 year ago
    Are you using any threading or Grand Central Dispatch in your code? A Kotlin object must be frozen before passing it between threads.
    Michael Pohl

    Michael Pohl

    1 year ago
    I don't think so. As stated above, I just followed this very basic tutorial provided by jetbrains, there is just a single api call and very basic ui.
    Ok, I've figured it out myself now. Android Studio automatically added the import statements as I was typing, but didn't always pick the correct one. So I had to go through all the files and double-check the imports, since it all looked correct in the IDE.