I'm trying to use Ktor on iOS through a Kotin Mult...
# ktor
g
I'm trying to use Ktor on iOS through a Kotin Multiplatform project. But I keep getting
kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen
error when i'm using on iOS ( the android part work well BTW ) I've defined a specific dispatcher for iOS like this :
Copy code
internal val ApplicationDispatcher: CoroutineDispatcher = NsQueueDispatcher(dispatch_get_main_queue())

internal class NsQueueDispatcher(
    private val dispatchQueue: dispatch_queue_t
) : CoroutineDispatcher() {
    override fun dispatch(context: CoroutineContext, block: Runnable) {
        dispatch_async(dispatchQueue) {
            block.run()
        }
    }
}
And I use like this in a presenter that I will connect to the iOS UIViewController
Copy code
class ExampleViewPresenter : BasePresenter() {

   fun test() {
        launch {
            try {
                val example =  ExampleSuspendMethod() 

                withContext(Main) {
                    println(example)
                }

            } catch (e: Throwable) {
                println(e)
            }
        }
}
I've defined the scope of
launch
in BasePresenter like this:
Copy code
abstract class BasePresenter : CoroutineScope {

    private var job = Job()

    override val coroutineContext: CoroutineContext
        get() = ApplicationDispatcher + job

    fun onDestroy() {
        job.cancel()
    }

}
I've found people with the same error on stack overflow and on this channel but the cause was a bug in Kotlin
1.3.11
and I'm using
1.3.21
. I've found one similar project with the same version of Kotlin but I didn't succeed to make it work ( https://github.com/watabee/RakutenRankingKotlin ) Did anyone succeed to use Ktor client on iOS with Kotlin
1.3.21
?
e
Please note that coroutines is not supported between multiple threads. What is
Main
dispatcher in your code?
Here you could find the working sample with ktor iOS client: https://github.com/JetBrains/kotlinconf-app
g
Thanks ! I will take a look to the example.
Main
is not useful, old test code…
e
I’m having a similar issue. I’ve basically tried to get as much as I can from the KotlinConf app as I can but I’ve hit a brick wall. My code is open source so you can poke it with a stick if you want: https://github.com/bakkenbaeck/porchpirateprotector
it seems to be actually hitting it in the
post
request - I tried pulling out the
HttpRequestBuilder
to a var instead of using a lambda, and it managed to get to the actual request before dying
to
Copy code
val fullPath = fullURLStringForPath(path)
        var builder = HttpRequestBuilder()
        builder.url(fullPath)
        builder.body = data
        headers.forEach { builder.header(it.key, it.value) }
        println("POSTUN $data")

        return <http://ktorClient.post|ktorClient.post>(builder)
still hitting that
println
before it throws the exception
OK, maybe I found something? Diving through code from
<http://HttpClient.post|HttpClient.post>
down to
HttpClient.request(Builder)
to
call.builder
, I found this in
io.ktor.client.call
- the comments certainly say it mutates.
oops sorry, this is called from
io.ktor.client.call.utils.kt
- it’s in
io.ktor.client.request.HttpRequest.kt
Pretty much everything from the convenience
post
/
get
etc methods goes through this which calls that:
g
Is your HttpClient a property of a singleton (
object
) ?
e
@gonzooin yes, it is!
have you found that to be an issue?
r
We’re experimenting right now, but it may be the cause
e
interesting! I’ll poke at that and see what i come up with
r
Yeah this was the issue. It still doesn’t work but because of the next error in line. Don’t store an
HttpClient
instance inside an
object
@e5l it would be nice to have a warning of that somewhere, because you don’t expect an HttpClient to crash when it’s frozen. This is also the solution to https://github.com/ktorio/ktor/issues/887
e
@ribesg @gonzooin I got it working! a big piece of it was the fact that it was on an
object
, so thank you
The stuff that got frozen when it came back I was able to deal with by kicking back to Swift code
it’s cheating, but that’s my kind of cheating 🙂
g
Congrats on that 👏 We figured out by keeping a reference to httpClient from Swift ( for summarize the solution 😄 )
e
Awesome thanks for the investigation, probably I have an idea how to fix the issue with client in object and try to implement it in next release 🙂
👍 1