Kotlin Multiplatform Mobile: Flow<List<*SomeModel*>> сопоставляется с Flow<NSArray> в iOS

Мой общий модуль содержит класс Repository, который имеет две функции, которые возвращают список элементов, заключенных в пользовательский класс, расширяющий Flow, называемый CFlow.

Код для CFlow я взял из kotlinconf-app и здесь:

fun <T> Flow<T>.asCFlow(): CFlow<T> = CFlow(this)

class CFlow<T>(private val origin: Flow<T>) : Flow<T> by origin {

    fun watch(block: (T) -> Unit): Closeable {
        val job = Job()

        onEach {
            block(it)
        }.launchIn(CoroutineScope(Dispatchers.Main + job))

        return object : Closeable {
            override fun close() {
                job.cancel()
            }
        }
    }
}

Примеры функций репозитория:

fun getData1(): CFlow<List<Profile>>

fun getData2(): CFlow<List<String>>

Когда я пытаюсь вызвать эти функции в быстром коде iOS, возвращаемый тип функций преобразуется в CFlow<NSArray>, а внутри функции просмотра используется тип массива Any.

Это странно, потому что и в kotlinconf-app , и в здесь возвращаемые типы функций сохранены, и в их кодовой базе не задействовано приведение типов.

Вопрос: Как я могу сделать так, чтобы тип CFlow был известен в проекте Xcode iOS?

Версия Android Studio: 4.1.1

Kotlin lang и версия плагина: 1.4.21

Версия плагина Kotlin Multiplatform Mobile: 0.2.0

Версия Xcode: 12.2

2
0
1 419
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это потому, что в Objective-C нет дженериков. Массивы — это упорядоченные наборы объектов.

Таким образом, использование любого универсального типа коллекции в Kotlin потеряет свой тип при переводе на NSArray.

Я считаю, что у вас есть три варианта:

  1. Дождитесь прямого взаимодействия Kotlin — Swift (которое в настоящее время отложено)
  2. Приведение значений в Swift
  3. Не используйте дженерики с коллекциями. Я лично не использую оболочку Flow в настоящее время и делаю что-то вроде этого:
fun observeItems(onChange: (List<Item>) -> Unit) {
        items.onEach {
            onChange(it)
        }.launchIn(coroutineScope)
    }

Предоставление функции удаления для iOS

fun dispose() {
    coroutineScope.cancel()
}

И потреблять так:

repo.observeItems { items in
    ...
}

Но определенно это больше работы, и, надеюсь, эти проблемы взаимодействия будут решены по ходу дела.

Спасибо за ваш ответ. Это помогло прояснить ситуацию

Marat 04.03.2021 21:20

сейчас компилятор не может понять вложенные дженерики. в качестве обходного пути на данный момент оберните свой список внутри класса данных, подобного этому

data class ProfileResult(val data: List<Profile>)

fun getData1(): CFlow<ProfileResult>

это даст вам конкретный тип в ios

Спасибо за ваш ответ. Это помогло прояснить ситуацию

Marat 04.03.2021 21:20

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