Задержка сопрограмм Kotlin не работает в диспетчере очереди iOS

У меня есть приложение KMM, и есть код:

      fun getWeather(callback: (WeatherInfo) -> Unit) {
        println("Start loading")
        GlobalScope.launch(ApplicationDispatcher) {
            while (true) {
                val response = httpClient.get<String>(API_URL) {
                    url.parameters.apply {
                        set("q", "Moscow")
                        set("units", "metric")
                        set("appid", weatherApiKey())
                    }
                    println(url.build())
                }
                val result = Json {
                    ignoreUnknownKeys = true
                }.decodeFromString<WeatherApiResponse>(response).main
                callback(result)

                // because ApplicationDispatcher on IOS do not support delay
                withContext(Dispatchers.Default) { delay(DELAY_TIME) }
            }
        }
    }

И если я заменю withContext(Dispatchers.Default) { delay(DELAY_TIME) } с участием delay(DELAY_TIME) выполнение никогда не возвращается в цикл while, и у него будет только одна итерация.

А для IOS выглядит так:

      internal actual 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()
        }
    }
}

И из delay исходный код, я могу догадаться, что DefaultDelay должен быть возвращен, и должно быть аналогичное поведение с / без withContext(Dispatchers.Default)

      /** Returns [Delay] implementation of the given context */
internal val CoroutineContext.delay: Delay get() = get(ContinuationInterceptor) as? Delay ?: DefaultDelay

Спасибо!

PS у меня есть ApplicationDispatcherиз ктор-образцов .

1 ответ

Наверное ApplicationDispatcher это что-то старое, вам больше не нужно его использовать:

      CoroutineScope(Dispatchers.Default).launch {

}

или же

      MainScope().launch {

}

И не забывайте использовать -native-mtверсия сопрограмм, подробнее в этом выпуске

Другие вопросы по тегам