Сборка iOS-фреймворка и подключение к Xcode
Как общий Kotlin-модуль попадает в Xcode и становится обычной зависимостью Swift-проекта.
XCFramework — упаковка скомпилированного Kotlin/Native-кода в формат, который Xcode подключает как библиотеку, с заголовками Objective-C для вызова из Swift.
Что именно собирается для iOS
Для iOS Kotlin/Native генерирует .framework — бинарник плюс сгенерированные Objective-C заголовки. Из этих заголовков Swift «видит» ваши классы и функции. Чтобы упаковать сразу несколько архитектур (устройство + симулятор) в один артефакт, используют XCFramework.
kotlin {
val xcf = XCFramework()
listOf(iosX64(), iosArm64(), iosSimulatorArm64()).forEach {
it.binaries.framework {
baseName = "Shared"
xcf.add(this)
}
}
}Два способа подключения
Первый — прямая интеграция: Xcode при сборке вызывает Gradle-задачу, которая пересобирает фреймворк. Удобно, пока общий код и iOS-приложение в одном репозитории. Второй — публикация XCFramework (например, через CocoaPods или Swift Package Manager) и подключение как внешней зависимости. Это лучше, когда iOS-команда работает отдельно и не хочет держать у себя Kotlin-тулчейн.
Прямая интеграция через скрипт сборки
В настройках Xcode-таргета добавляют Run Script Phase, который дёргает Gradle:
cd "$SRCROOT/.."
./gradlew :shared:embedAndSignAppleFrameworkForXcodeЭта задача собирает фреймворк под текущую конфигурацию (Debug/Release, устройство/симулятор) и кладёт туда, где Xcode его подхватит.
Как это выглядит в Swift
После подключения общий модуль импортируется как обычный фреймворк:
import Shared
let repo = OrderRepository()
repo.loadOrders { orders, error in
// orders — это ваши Kotlin-модели, видимые из Swift
}Как работает под капотом
Компилятор Kotlin/Native экспортирует публичный API общего модуля в виде Objective-C интерфейса (заголовочный файл .h внутри фреймворка). Swift поверх Objective-C работает прозрачно, поэтому Kotlin-классы выглядят почти как Swift-типы. «Почти» — потому что трансляция не идеальна: generic'и, корутины и enum'ы маппятся с оговорками, которые мы разберём в разделе про интероп.
Частые ошибки
Типичная проблема — собрали фреймворк под устройство, а запускают на симуляторе (или наоборот), и Xcode ругается на несовместимую архитектуру. XCFramework решает это, упаковывая все варианты. Вторая ошибка — менять Kotlin-код и не пересобирать фреймворк; при прямой интеграции скрипт делает это сам, но при ручном подключении легко получить «старую» версию API.
Итоги
- iOS получает общий код в виде
.framework/XCFramework с Obj-C заголовками. - Подключать можно прямой интеграцией (Gradle из Xcode) или как опубликованную зависимость.
- В Swift общий модуль импортируется обычным
import. - XCFramework избавляет от путаницы «устройство против симулятора».