Кросплатформна розробка мобільного застосунку на Kotlin Multiplatform
Kotlin Multiplatform вийшов із Beta та отримав статус Stable у листопаді 2023 — з KMP 1.9.20. Це не «пиши один раз — запускай скрізь» у сенсі Flutter. KMP дозволяє розділити бізнес-логіку між iOS та Android, зберігши нативний UI на кожній платформі. Архітектурно: спільний модуль на Kotlin компілюється в JVM bytecode для Android та в нативний фреймворк через Kotlin/Native для iOS (xcframework через Gradle завдання assembleXCFramework).
Головне наслідство: ніяких компромісів у UI — SwiftUI на iOS, Jetpack Compose на Android. Ніякого «одинакового зовнішнього вигляду на обох платформах» — кожна платформа виглядає нативно. Shared layer — тільки commonMain: сітьовий шар, бізнес-логіка, доменні моделі, локальна БД.
Що виносимо у shared, що залишається нативним
В commonMain: сітьові запити через Ktor Client (io.ktor:ktor-client-core), серіалізація через kotlinx.serialization, локальна БД через SQLDelight (генерує типізований Kotlin API з SQL-файлів), доменні моделі, use cases, ViewModels через kotlinx.coroutines + StateFlow.
Залишається нативним: UI повністю (SwiftUI / UIKit на iOS, Compose / XML на Android), доступ до камери, біометрія, push-повідомлення (APNs vs FCM), нативні платіжні SDK. Доступ до залежних від платформи API — через механізм expect/actual: у commonMain оголошуємо expect class PlatformSpecific, у androidMain та iosMain пишемо actual реалізації.
Типова біль Kotlin/Native — багатопоточність. До KMP 1.7.20 будь-який об'єкт, створений в одному потоці, не міг бути доступен з іншого — InvalidMutabilityException. З появою нового MM (Memory Manager) у 1.7.20 це обмеження знято, але legacy-код може містити паттерни з freeze(), які тепер застарілі. При аудиті старих KMP-проектів це перше, що дивимо.
Інтеграція на стороні iOS
xcframework підключається в Xcode через SPM (Swift Package Manager) або Cocoapods з pod 'shared'. SPM-інтеграція префікс з XCode 15+: binaryTarget у Package.swift з локальним шляхом до xcframework. Оновлення фреймворку — ./gradlew assembleXCFramework у Gradle, потім build в Xcode.
Вклик suspend-функцій із Swift вимагає обгорток: Swift не викликає Kotlin coroutines напрямки. Рішення — KMMBridge від Touchlab або ручні обгортки через Kotlinx.coroutines + CoroutineScope на Kotlin-стороні, експортуючі callback-based API. З Kotlin 1.9.20 є експериментальний @Throws + Swift async/await через kotlin.native.concurrent, але у продакшені вимагає тестування.
Кейс. Фінтех-застосунок: iOS (SwiftUI + Combine) та Android (Compose + Flow) діляють спільну бізнес-логіку — розрахунок кредитних лімітів, валідація форм, кешування через SQLDelight. Ktor Client настроєний з OkHttp engine на Android та Darwin (NSURLSession) engine на iOS. Спільний AuthInterceptor у commonMain додає JWT-токен у кожен запит. Тести shared-модуля — kotlin.test + runTest для корутин. CI — GitHub Actions: ./gradlew :shared:allTests запускає тести під JVM та через K/N test runner на симуляторі iOS.
SQLDelight vs Room vs Realm
| БД | Підтримка Shared | Тип API | Підходить для |
|---|---|---|---|
| SQLDelight | Так (commonMain) | Типізований Kotlin з SQL | KMP-проекти |
| Room | Тільки Android | DAO + Kotlin | Тільки Android |
| Realm Kotlin | Так (commonMain) | Object-oriented | Реактивні застосунки |
SQLDelight — наш вибір за замовчуванням для KMP: SQL-схема одна, API генерується під обидві платформи.
Терміни
| Масштаб | Приблизні терміни |
|---|---|
| Shared бізнес-логіка + нативний UI, MVP | 10–16 тижнів |
| Повноцінний продукт з оффлайном | 5–9 місяців |
| Міграція існуючого Android-застосунку | 3–6 місяців |
Вартість розраховується індивідуально. KMP вимагає команди з компетенціями в обох нативних платформах — це ключовий фактор при оцінці бюджету.







