Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/hhru/kotlin-swift-interopedia


https://github.com/hhru/kotlin-swift-interopedia

Last synced: 3 months ago
JSON representation

Awesome Lists containing this project

README

        

# Kotlin-Swift interopedia
[![Maven Central](https://img.shields.io/maven-central/v/org.jetbrains.kotlin/kotlin-maven-plugin.svg)](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.jetbrains.kotlin%22)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Мы создали этот репозиторий, чтобы помочь разработчикам, интересующимся технологией KMM, понять, как будет выглядеть
описанное ими публичное API общего модуля.

В сети есть [подробная документация от JetBrains](https://kotlinlang.org/docs/native-objc-interop.html)
про интероп между Kotlin и Swift, однако в ней не рассматриваются подробно все возможности языка Kotlin.

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

## Таблица интеропа

Как пользоваться таблицей:

- Знак :white_check_mark: означает, что указанной фичой Kotlin-а можно спокойно пользоваться, она генерирует
Swift-friendly код без необходимости доработок;
- Знак :warning: означает, что либо для работы фичи требуются какие-то доработки, либо есть несоответствие между
ожидаемым и реальным поведением фичи, которое не сильно мешает разработке;
- Знак :no_entry_sign: означает, что фичой нельзя пользоваться, она генерирует не Swift-friendly код, она работает
совсем не так как ожидается, и это может стать помехой в разработке.



Фича Kotlin-а
Ожидание
Статус
Комментарий



Common


Internal modifier
Internal-функции и классы не видны в Swift
:white_check_mark:
Так и есть, с iOS-разработчиками придётся обсуждать только публичное API общего кода


JavaDoc comments
Комментарии видны в XCode
:warning:
Комментарии видны, если добавить специальный аргумент для компилятора


Data types


Primitive types
Типы, объявленные в Kotlin, можно без изменений использовать в Swift
:warning:
Может требоваться маппинг для целочисленных типов данных / маппинги для Char-а


Optional (nullable) primitive types
Тип, объявленный как Nullable, является таковым и на стороне Swift / Пользоваться nullable-типами можно без изменений
:warning:
Для примитивных типов требуется маппинг в специальные optional-типы / особенности с Char?


Mutable, immutable collections
Сигнатуры List / MutableList / etc имеют значение в Swift-мире и тоже регулируют мутабельность ; Использование коллекций не отличается от Kotlin
:warning:
Для регулировки мутабельности используются ключевые слова let, var / Для мутабельных коллекций требуются дополнительные маппинги


Collections with primitive types
Коллекции с элементами примитивных типов не требуют дополнительных маппингов
:warning:
Маппинги не требуются только для String-типа


Collections with custom types data
Коллекции с элементами кастомных типов не требуют дополнительных маппингов
:white_check_mark:
Маппинги не требуются :thumbsup:


Unit and Nothing
Типы Unit и Nothing можно использовать так же, как в Kotlin: Unit как объект или void, Nothing - нельзя создать
:white_check_mark:
Реальность соответствует ожиданиям :thumbsup:


Usual workflow


Top-level functions
Функцию можно использовать напрямую после импорта, аналогично Kotlin-у
:warning:
Появляется класс-обёртка: UtilityKt.topLevelFunction()


Top-level val properties (readonly)
Доступ к свойству можно получить напрямую после импорта, аналогично Kotlin-у / поле readonly
:warning:
Появляется класс-обёртка для доступа к свойству: UtilityKt.propertyVal


Top-level var properties (mutable)
Доступ к свойству можно получить напрямую после импорта, аналогично Kotlin-у / поле mutable
:warning:
Появляется класс-обёртка для доступа к свойству: UtilityKt.propertyVar


Extension function over platform class
Функцию можно использовать на объекте платформенного класса
:warning:
Появляется класс-обёртка с методом, принимающим объект нужного класса


Extension properties over platform class
Доступ к свойству можно получить с помощью объекта платформенного класса
:warning:
Появляется класс-обёртка с методом, принимающим объект нужного класса


Extension properties for companion object of platform class
Доступ к свойству можно получить с помощью платформенного класса
:no_entry_sign:
В .h-файле свойство есть, а в Swift-е не получается использовать


Extension functions over usual class
Функцию можно использовать на объекте класса
:white_check_mark:
Реальность соответствует ожиданиям :thumbsup:


Extension properties over usual class
Доступ к свойству можно получить через объект класса
:white_check_mark:
Реальность соответствует ожиданиям :thumbsup:


Extension properties for companion object of usual class
Доступ к свойству можно получить через класс
:warning:
Доступ к свойству можно получить через объект companion


Usual class constructor
Работа с конструктором не отличается от Kotlin-а
:white_check_mark:
Реальность соответствует ожиданиям :thumbsup:


Usual class val property (readonly)
Доступ к свойству есть из объекта класса / свойство readonly
:white_check_mark:
Реальность соответствует ожиданиям :thumbsup:


Usual class var property (mutable)
Доступ к свойству есть из объекта класса / свойство mutable
:white_check_mark:
Реальность соответствует ожиданиям :thumbsup:


Usual class functions
Работа с функциями, объявленными внутри класса, не отличается от Kotlin-а
:white_check_mark:
Реальность соответствует ожиданиям :thumbsup:


Companion object
Доступ к свойствам и функциям, объявленным в companion object-е, аналогичен Kotlin-у
:warning:
Доступ есть через вспомогательный объект companion


Objects
Доступ к свойствам и функциям, объявленным в object-е, аналогичен Kotlin-у
:warning:
Доступ есть через вспомогательный объект shared


Function with default arguments
Работа с функциями, имеющими дефолтные аргументы, аналогична Kotlin-у
:no_entry_sign:
Всегда приходится указывать все аргументы функции


Constructor with default arguments
Работа с конструктором, имеющим дефолтные аргументы, аналогична Kotlin-у
:no_entry_sign:
Всегда приходится указывать все аргументы для конструктора


Classes


Abstract class
Можно отнаследоваться от абстрактного класса, IDE подсказывает какие методы надо переопределить
:warning:
В IDE нет подсказок о необходимости переопределить абстрактный метод


Annotation class
Аннотации можно использовать в Swift
:no_entry_sign:
Аннотации не попали в .h-файл


Data class
Data class-ы сохраняют свои свойства после перехода в Swift
:warning:
Не все возможности data class-ов сохраняются / есть особенности с copy


Enum class
Kotlin-овский enum class превратится в enum Swift-а, и можно будет использовать switch
:warning:
Не работает как ожидается. Но сгенерировался объект со статическими элементами


Inner class
Можно создать инстанс inner-класса / прямого доступа к родительским свойствам и функциям нет
:warning:
Небольшие отличия в синтаксисе создания


Open class
Можно наследоваться от open-класса / есть доступ к protected-полям / можно переопределять open-методы
:white_check_mark:
Можно переопределять и final-методы


Sealed class
Корректно конвертируется в структуру, которую можно передать в switch-конструкцию и сделать exhaustive
:no_entry_sign:
Генерируется класс с наследниками. Передав в switch нет подсказок об exhaustive


Value class
Класс попадёт в .h-файл, им можно будет пользоваться в Swift
:no_entry_sign:
Класс не попал в .h-файл, пользоваться нельзя


Interfaces


Interface
При реализации интерфейса, IDE подставит заглушки для всего
:white_check_mark:
Интерфейс стал @protocol-ом. Но почему-то val-свойство превратилось в var


Sealed interface
При использовании в switch IDE поможет рассмотреть все варианты
:no_entry_sign:
Сгенерировались отдельные протоколы, не связанные между собой


Fun interface
С помощью такого протокола можно более простым синтаксисом описать лямбду
:no_entry_sign:
В Swift нельзя создать анонимный класс


Functions


DSL
Надеемся, что DSL в Kotlin-е превратится в DSL на Swift
:warning:
Сгенерировались функции с receiver-ами, выглядит не так удобно, как хотелось бы


Function returns lambda
Функция, вернувшая лямбду, работает без крашей; лямбду можно вызвать
:white_check_mark:
Реальность совпадает с ожиданием


Function returns primitive type
Функция, возвращающая примитивный тип, работает без ошибок
:white_check_mark:
Реальность совпадает с ожиданием


Function with extension function as args
Можно вызвать функцию так же, как в Kotlin
:warning:
Extension-функция превращается в лямбду с параметром


Function with lambda arguments
Функция, принимающая в аргументах одну или несколько лямбд, нормально конвертируется в Swift
:white_check_mark:
Реальность совпадает с ожиданием


Function with no return type
Функции, которые ничего не возвращают, можно спокойно вызвать
:white_check_mark:
Реальность совпадает с ожиданием


Function with value class parameter
Функция появится в .h-файле и её можно будет использовать, передавая value-класс
:no_entry_sign:
Функция появилась в .h-файле, но аргумент value-класса развернулся в примитивы


Function with vararg parameter
vararg смапился в Swift-овый variardic и используется аналогично
:no_entry_sign:
Не работает так, как ожидается


Functions with overloads
Использование перегруженных функций ничем не отличается от Kotlin-а
:warning:
Есть особенности при использовании одинаковых имён параметров


Inline functions
Инлайн-функции есть в .h-файле, их можно вызвать
:white_check_mark:
Реальность совпадает с ожиданием


Suspend functions
Suspend-функции развернулись в удобную для Swift-конструкцию
:warning:
Транслируется в callback, экспериментально - в async / await. Но для использования в реактивных фреймворках требуются дополнительный bridge-код


Generics


Generic classes
Сгенерируется класс с generic-ом, пользоваться можно как в Kotlin
:warning:
Есть некоторые особенности использования типов


Generic functions
Обычная функция-generic позволяет принять аргумент любого типа
:no_entry_sign:
Нет автоматического вывода типа, особенности nullability


Generic interfaces
Можно реализовать протокол с generic-ом после перехода в Swift
:no_entry_sign:
Generic-и на интерфейсах не поддерживаются


Bounded generics
Ограничение типа generic-а, объявленное в Kotlin, сработает и в Swift
:no_entry_sign:
Ограничение не сработало


Contravariant generics
При указании ключевого слова in на generic-е, сгенерируется generic со схожим поведением (контравариантный generic)
:no_entry_sign:
Не работает как ожидается, приходится использовать приведение типов


Covariant generics
При указании ключевого слова out на generic-е, сгенерируется generic со схожим поведением (ковариантный generic)
:no_entry_sign:
Не работает как ожидается, приходится использовать приведение типов


Star projection
Сгенерируется generic со схожим поведением (in Nothing / out Any?)
:no_entry_sign:
Не работает как ожидается, приходится использовать приведение типов


Reified functions
Функции с reified нормально вызываются из Swift + работают ожидаемым образом
:no_entry_sign:
В рантайме функция крашится

## Полезные ссылки
- Из документации Kotlin
- [Документация: Что нового в Kotlin 1.5.30](https://kotlinlang.org/docs/whatsnew1530.html)
- [Документация: интероп Swift <--> Kotlin](https://kotlinlang.org/docs/native-objc-interop.html).
- [Документация: маппинг типов между C и Kotlin/Native](https://kotlinlang.org/docs/mapping-primitive-data-types-from-c.html)
- [Документация: Туториал по использованию Ktor-а в multiplatorm](https://kotlinlang.org/docs/mobile/use-ktor-for-networking.html#set-up-an-http-client)
- [Документация: Kotlin-идиомы](https://kotlinlang.org/docs/idioms.html)
- [Документация: Concurrency в Kotlin/Native](https://kotlinlang.org/docs/mobile/concurrency-overview.html)
- [Документация Apple: Про completion handler-ы](https://developer.apple.com/documentation/swift/calling_objective-c_apis_asynchronously)
- [Документация Swift: про async / await](https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html)
- [Доклад: Состояние интеропа в 2019 году (Некоторые вещи всё ещё актуальны)](https://www.youtube.com/watch?v=N1Xt-LuAR9A&ab_channel=JetBrainsTV)
- [Статья: Про Kotlin/Native generics в 2019 году (Всё ещё актуально)](https://medium.com/@kpgalligan/kotlin-native-interop-generics-15eda6f6050f)
- [Статья: Про построение более удобного кода на Swift при помощи gradle-плагина moko-kswift](https://habr.com/ru/post/571714/)
- [Статья: Построение DSL в Swift](https://habr.com/ru/company/tinkoff/blog/455760/).
- Серия статей про написание необходимых обёрток для взаимодействия между корутинами и RxSwift / Combine / OpenCombine
- [Статья: Использование suspend в Swift - про неудобство с RxSwift](https://dev.to/touchlab/working-with-kotlin-coroutines-and-rxswift-24fa)
- [Статья: Использование suspend в Swift в 2021 году](https://touchlab.co/kotlin-coroutines-swift-revisited/)
- [Github: Пример работы корутин с RxSwift / Combine на основе статей от Touchlab](https://github.com/touchlab/SwiftCoroutines)
- Набор статей про Generic-и в Kotlin:
- [Хорошая статья про ковариантность и контравариантность в Kotlin](https://typealias.com/guides/illustrated-guide-covariance-contravariance/)
- [Хорошая статья про in и out в Kotlin](https://typealias.com/guides/ins-and-outs-of-generic-variance/)
- [Хорошая статья про star projection](https://typealias.com/guides/star-projections-and-how-they-work/)
- [Github: Список DSL-библиотек на Swift](https://github.com/carson-katri/awesome-result-builders)
- [Плагин moko-kswift](https://github.com/icerockdev/moko-kswift/)