Interesting thing happened to me. I know its horri...
# compose-ios
j
Interesting thing happened to me. I know its horrible code, but if using in a class member like: val variable = runBlocking { listOf(fetchData) } This works in Android but not in iOS, in iOS my entire screen was white without a trace saying why this happening. After a gazillion debug flows I randomly got a crash from coroutines in iOS threads handling. Now I am curious, why does this happening? ๐Ÿ˜›
a
You might be getting a deadlock on the main thread.
j
Why is that happening on iOS but not Android? Absolutely this is very bad code like this. Just want to understand what the error was so I can avoid it in future. I have some more runBlocking things and would like to be sure those do not causing this issue. I think also its the combination of iOS viewcontroller root level injecting Koin component, that creating both the class mention above waiting but also waiting for the composable to be created at the same time, causing the deadlock. But still interesting.
a
I might be wrong, but my understanding is that Android and iOS impls dispatch the continuation differently. I think Android impl schedules a job on background thread, then suspends, and then the continuation is called directly from the background thread. Whereas iOS dispatches from the background thread on main thread before calling the continuation, which is blocked.
j
Does this also differs between desktop and web/wasm targets btw if you know? ๐Ÿ™‚ Just trying to see how to avoid painpoints of differences in coroutines in KMP manner.
a
I think it depends on what
fetchData
is.
One pain point to avoid is
runBlocking
๐Ÿ™‚
โž• 1
j
FetchData could be any async thing from server, database or such.
a
Yeah, and the behaviour largely depends on that implementation. E.g. I think Ktor iOS dispatches responses on the main queue on iOS, so it should certainly cause a deadlock if the main thread is blocked.
j
Right, yeah mixing stuff like androidx datastore, sqdelight, ktor and firestore ๐Ÿ™‚ I guess importance of using correct withContext here from case to case. However coroutines for iOS not supporting all dispatcher variants I think yet?
a
iOS should now support all standard dispatchers, I believe.
j
Oh from which kotlinx coroutine version if you know? ๐Ÿ˜ฎ Because I overload them now in Koin with "wrong" iOS implementation ๐Ÿ˜›
Problably wrong doing this:
Copy code
factory<CoroutineContext>(named(CoroutineDispatchersName.IoDispatcher)) { IosMainDispatcher }
    factory<CoroutineContext>(named(CoroutineDispatchersName.DefaultDispatcher)) { IosMainDispatcher }
    factory<CoroutineContext>(named(CoroutineDispatchersName.MainDispatcher)) { IosMainDispatcher }
Copy code
object IosMainDispatcher : CoroutineDispatcher() {
    override fun dispatch(context: CoroutineContext, block: Runnable) {
        dispatch_async(dispatch_get_main_queue()) { block.run() }
    }
}
I couldnt find equivalent to Dispatchers.IO in Darwin. But bad documented, so I dont understand what I should be using.
a
Yeah, looks like all your dispatchers are
Main
. You should be able to use Dispatchers.Main, Dispatchers.Default, Dispatchers,IO, etc. IO is documented here: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-i-o.html
j
Ah the Dispatchers.IO was an extension I had to import, which didnt exist in the past for me. Nice, finally I can use commonMain for coroutines for this and throw away my horrible shit solution run everything in main ๐Ÿ˜› Thank you so much!
K 1
The app went to be a lot more responsive in iOS now ๐Ÿ˜„ So huge success! Wow embarassing ๐Ÿ˜„