Рекомендуемая структура проекта Kotlin Multiplatform
Обзоры базовых и расширенных концепций структуры проекта должны помочь вам разобраться в наборах исходного кода и управлении зависимостями. А как насчёт модулей, которые объединяют наборы исходного кода и используют эти зависимости?
Оптимальная структура модулей
Оптимальная структура модулей может различаться в зависимости от ваших целей и необходимых целевых платформ. Вы можете изучить результат работы мастера плагина KMP IDE с различными конфигурациями и наборами целевых платформ, чтобы увидеть, как по умолчанию организуются проекты.
Общий подход можно описать следующим образом:
Точки входа ваших приложений должны находиться в отдельных модулях, каждый из которых зависит от необходимых модулей с общим кодом.
-
Общий код обычно разделяют на бизнес-логику и пользовательский интерфейс, при этом цель состоит в том, чтобы избежать ненужных зависимостей:
Если все приложения, созданные в рамках проекта KMP, используют как общий код пользовательского интерфейса, так и общую бизнес-логику, для всего общего кода может быть достаточно одного модуля
shared.Если пользовательский интерфейс какого-либо приложения написан с использованием нативного кода (например, вы реализовали интерфейс iOS на чистом Swift), имеет смысл отделить код пользовательского интерфейса от бизнес-логики, чтобы избежать зависимостей от Compose Multiplatform там, где они не нужны. Таким образом, можно создать модули
sharedLogicиsharedUIи добавлять их в качестве зависимостей к модулям точек входа по мере необходимости.
-
Если в проекте есть серверный код, которому нужно совместно использовать логику с клиентскими приложениями, рекомендуется организовать его следующим образом:
Папка
appс модулями точек входа и модулями общего клиентского кода, организованными описанным выше способом.Модуль
serverс кодом, специфичным для сервера.Модуль
coreс кодом, общим для сервера и клиентов, например моделями и проверкой данных.
Если в проекте используется устаревшая структура, в которой точки входа приложений и общий код находятся в одном модуле, воспользуйтесь приведёнными ниже инструкциями, чтобы вынести точки входа в отдельные модули.
Создание отдельных модулей для точек входа приложения
В качестве примера перехода к рекомендуемой структуре мы рассмотрим старый пример Compose Multiplatform, который можно найти в ветке old-project-structure репозитория с примерами.
Пример состоит из одного модуля Gradle (composeApp), который содержит весь общий код и точки входа KMP, а также папки iosApp с кодом и конфигурацией проекта iOS.
Чтобы вынести точку входа в отдельный модуль, нужно создать модуль, переместить код и соответствующим образом настроить как новый модуль, так и модуль с общим кодом.
Модуль для точки входа приложения Android
Создание и настройка модуля приложения Android
Чтобы создать модуль приложения Android (androidApp):
Создайте каталог
androidAppв корне проекта.В этом каталоге создайте пустой файл
build.gradle.ktsи каталогsrc.-
Добавьте новый модуль в настройки проекта в файле
settings.gradle.kts, добавив эту строку в конец файла:include(":androidApp") В главном меню выберите Сборка | Синхронизировать проект с файлами Gradle или нажмите кнопку обновления Gradle в редакторе.
Настройка сценария сборки приложения Android
Настройте сценарий сборки Gradle для нового модуля:
-
Добавьте плагин Kotlin Android Gradle в каталог версий в файле
gradle/libs.versions.toml:[plugins] kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } -
Укажите плагины, необходимые модулю приложения Android, в файле
androidApp/build.gradle.kts:plugins { alias(libs.plugins.kotlinAndroid) alias(libs.plugins.androidApplication) alias(libs.plugins.composeMultiplatform) alias(libs.plugins.composeCompiler) } -
Убедитесь, что все эти плагины указаны в файле
build.gradle.ktsв корневом каталоге:plugins { alias(libs.plugins.kotlinAndroid) apply false alias(libs.plugins.androidApplication) apply false alias(libs.plugins.composeMultiplatform) apply false alias(libs.plugins.composeCompiler) apply false // ... } -
Чтобы добавить необходимые зависимости, скопируйте существующие зависимости из блока
androidMain.dependencies {}сценария сборкиcomposeAppи добавьте зависимость от самого модуляcomposeApp. В этом примере результат должен выглядеть так:kotlin { dependencies { implementation(projects.composeApp) implementation(libs.androidx.activity.compose) implementation(libs.compose.uiToolingPreview) } } Скопируйте весь блок
android {}с конфигурацией, специфичной для Android, из файлаcomposeApp/build.gradle.ktsв файлandroidApp/build.gradle.kts.-
Скопируйте параметры компилятора из блока
androidTarget {}файлаcomposeApp/build.gradle.ktsв блокtarget {}файлаandroidApp/build.gradle.kts:kotlin { target { compilerOptions { jvmTarget.set(JvmTarget.JVM_11) } } } -
Измените конфигурацию модуля
composeAppс приложения Android на библиотеку Android, поскольку фактически он становится библиотекой. В файлеcomposeApp/build.gradle.kts:-
Измените ссылку на плагин Gradle:
alias(libs.plugins.androidApplication)alias(libs.plugins.androidLibrary) -
Удалите строки со свойствами приложения из блока
android.defaultConfig {}:defaultConfig { applicationId = "com.jetbrains.demo" minSdk = libs.versions.android.minSdk.get().toInt() targetSdk = libs.versions.android.targetSdk.get().toInt() versionCode = 1 versionName = "1.0" }defaultConfig { minSdk = libs.versions.android.minSdk.get().toInt() }
-
В главном меню выберите Сборка | Синхронизировать проект с файлами Gradle или нажмите кнопку обновления Gradle в редакторе.
Перемещение кода и запуск приложения Android
-
Переместите каталог
composeApp/src/androidMainв каталогandroidApp/src/, но учитывайте, что код, который должен оставаться кроссплатформенным:Код точки входа, например
MainActivity.ktв нашем примере, должен находиться в модулеandroidApp, чтобы приложение Android собиралось правильно.Все объявления expect и actual должны оставаться в наборах исходного кода общего модуля (
composeAppв нашем примере), чтобы быть доступными на всех платформах. После настройки зависимостиandroidAppотcomposeAppобъявления также станут доступны в коде точки входа.
Переименуйте каталог
androidApp/src/androidMainвmain.Если конфигурация настроена правильно, импорты в файле
androidApp/src/main/.../MainActivity.ktбудут работать, и код скомпилируется.-
Если вы используете IntelliJ IDEA или Android Studio, IDE распознает новый модуль и автоматически создаст новую конфигурацию запуска androidApp. Если этого не произошло, вручную измените конфигурацию запуска Android composeApp:
В раскрывающемся списке конфигураций запуска выберите Изменить конфигурации.
Найдите конфигурацию composeApp в категории Android.
В поле Общие | Модуль замените
demo.composeAppнаdemo.androidApp.
Запустите новую конфигурацию, чтобы убедиться, что приложение работает как ожидалось.
Если все работает правильно, удалите блок
kotlin.sourceSets.androidMain.dependencies {}из файлаcomposeApp/build.gradle.kts.
Вы вынесли точку входа Android в отдельный модуль. Теперь обновите модуль с общим кодом, чтобы использовать новый плагин библиотеки Android-KMP.
Настольное приложение JVM
Создание и настройка модуля настольного приложения
Чтобы создать модуль настольного приложения (desktopApp):
Создайте каталог
desktopAppв корне проекта.В этом каталоге создайте пустой файл
build.gradle.ktsи каталогsrc.-
Добавьте новый модуль в настройки проекта в файле
settings.gradle.kts, добавив эту строку:include(":desktopApp")
Настройка сценария сборки настольного приложения
Чтобы сценарий сборки настольного приложения работал:
-
Добавьте плагин Kotlin JVM Gradle в каталог версий в файле
gradle/libs.versions.toml:[plugins] kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } -
Укажите плагины, необходимые модулю общего пользовательского интерфейса, в файле
desktopApp/build.gradle.kts:plugins { alias(libs.plugins.kotlinJvm) alias(libs.plugins.composeMultiplatform) alias(libs.plugins.composeCompiler) } -
Убедитесь, что все эти плагины указаны в файле
build.gradle.ktsв корневом каталоге:plugins { alias(libs.plugins.kotlinJvm) apply false alias(libs.plugins.composeMultiplatform) apply false alias(libs.plugins.composeCompiler) apply false // ... } -
Чтобы добавить необходимые зависимости от других модулей, скопируйте существующие зависимости из блоков
commonMain.dependencies {}иjvmMain.dependencies {}сценария сборкиcomposeApp. В этом примере результат должен выглядеть так:kotlin { dependencies { implementation(projects.sharedLogic) implementation(projects.sharedUI) implementation(compose.desktop.currentOs) implementation(libs.kotlinx.coroutinesSwing) } } -
Скопируйте блок
compose.desktop {}с конфигурацией, специфичной для настольной платформы, из файлаcomposeApp/build.gradle.ktsв файлdesktopApp/build.gradle.kts:compose.desktop { application { mainClass = "compose.project.demo.MainKt" nativeDistributions { targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) packageName = "compose.project.demo" packageVersion = "1.0.0" } } } В главном меню выберите Сборка | Синхронизировать проект с файлами Gradle или нажмите кнопку обновления Gradle в редакторе.
Перемещение кода и запуск настольного приложения
После завершения настройки переместите код настольного приложения в новый каталог:
Создайте новый каталог
mainв каталогеdesktopApp/src.Переместите каталог
composeApp/src/jvmMain/kotlinв каталогdesktopApp/src/main/. Важно, чтобы координаты пакета соответствовали конфигурацииcompose.desktop {}.Если конфигурация настроена правильно, импорты в файле
desktopApp/src/main/.../main.ktбудут работать, и код скомпилируется.-
Чтобы запустить настольное приложение, измените конфигурацию запуска composeApp [jvm]:
В раскрывающемся списке конфигураций запуска выберите Изменить конфигурации.
Найдите конфигурацию composeApp [jvm] в категории Gradle.
В поле Проект Gradle замените
ComposeDemo:composeAppнаComposeDemo:desktopApp.
Запустите обновленную конфигурацию, чтобы убедиться, что приложение работает как ожидалось.
-
Если все работает правильно:
Удалите каталог
composeApp/src/jvmMain.-
Удалите код, связанный с настольной платформой, из файла
composeApp/build.gradle.kts:блок
compose.desktop {},блок
jvmMain.dependencies {}внутри блока KotlinsourceSets {},объявление целевой платформы
jvm()внутри блокаkotlin {}.
Веб-приложение
Создание и настройка модуля веб-приложения
Чтобы создать модуль веб-приложения (webApp):
Создайте каталог
webAppв корне проекта.В этом каталоге создайте пустой файл
build.gradle.ktsи каталогsrc.-
Добавьте новый модуль в настройки проекта в файле
settings.gradle.kts, добавив эту строку в конец файла:include(":webApp")
Настройка сценария сборки веб-приложения
Чтобы сценарий сборки веб-приложения работал:
-
Укажите плагины, необходимые модулю общего пользовательского интерфейса, в файле
webApp/build.gradle.kts:```kotlin plugins { alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.composeMultiplatform) alias(libs.plugins.composeCompiler) } ``` -
Убедитесь, что все эти плагины указаны в файле
build.gradle.ktsв корневом каталоге:plugins { alias(libs.plugins.kotlinMultiplatform) apply false alias(libs.plugins.composeMultiplatform) apply false alias(libs.plugins.composeCompiler) apply false // ... } -
Скопируйте объявления целевых платформ JavaScript и Wasm из файла
composeApp/build.gradle.ktsв блокkotlin {}файлаwebApp/build.gradle.kts:kotlin { js { browser() binaries.executable() } @OptIn(ExperimentalWasmDsl::class) wasmJs { browser() binaries.executable() } } -
Добавьте необходимые зависимости от других модулей:
kotlin { sourceSets { commonMain.dependencies { implementation(projects.sharedLogic) // Provides the necessary entry point API implementation(compose.ui) } } } В главном меню выберите Сборка | Синхронизировать проект с файлами Gradle или нажмите кнопку обновления Gradle в редакторе.
Перемещение кода и запуск веб-приложения
После завершения настройки переместите код веб-приложения в новый каталог:
Переместите весь каталог
composeApp/src/webMainв каталогwebApp/src. Если конфигурация настроена правильно, импорты в файлеwebApp/src/webMain/.../main.ktбудут работать, и код скомпилируется.Обновите имя сценария в файле
webApp/src/webMain/resources/index.html: заменитеcomposeApp.jsнаwebApp.js.-
Чтобы запустить веб-приложение, измените конфигурацию запуска composeApp [wasmJs]:
В раскрывающемся списке конфигураций запуска выберите Изменить конфигурации.
Найдите конфигурацию composeApp [wasmJs] в категории Gradle.
В поле Проект Gradle замените
ComposeDemo:composeAppнаComposeDemo:webApp.
Повторите эти действия для composeApp [js], чтобы также запускать версию JavaScript.
Запустите конфигурации, чтобы убедиться, что приложение работает как ожидалось.
-
Если все работает правильно:
Удалите каталог
composeApp/src/webMain.-
Удалите код, связанный с веб-платформой, из файла
composeApp/build.gradle.kts:блок
webMain.dependencies {}внутри блока KotlinsourceSets {},объявления целевых платформ
js {}иwasmJs {}внутри блокаkotlin {}.
Настройка общего модуля
В примере приложения используются общий пользовательский интерфейс и общая бизнес-логика, поэтому для всего общего кода достаточно одного общего модуля: можно просто переоборудовать composeApp в модуль общего кода.
Единственное изменение конфигурации Gradle, не связанное с подключением модулей точек входа, — это новый плагин Android Library Gradle. Этот плагин создан специально для многоплатформенных проектов и необходим для использования AGP 9 и более поздних версий.
Необходимые изменения:
-
Добавьте плагин библиотеки Android-KMP в каталог версий в файле
gradle/libs.versions.toml:[plugins] androidMultiplatformLibrary = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" } -
Добавьте плагины, необходимые модулю общего пользовательского интерфейса, в файл
composeApp/build.gradle.kts:plugins { alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.androidMultiplatformLibrary) alias(libs.plugins.composeMultiplatform) alias(libs.plugins.composeCompiler) } -
Добавьте следующую строку в корневой файл
build.gradle.kts, чтобы избежать конфликтов при применении плагина:alias(libs.plugins.androidMultiplatformLibrary) apply false
-
В файле
composeApp/build.gradle.ktsзамените блокkotlin.androidTarget {}блокомkotlin.androidLibrary {}:androidLibrary { namespace = "compose.project.demo.composedemo" compileSdk = libs.versions.android.compileSdk.get().toInt() compilerOptions { jvmTarget = JvmTarget.JVM_11 } androidResources { enable = true } } Удалите корневой блок
android {}из файлаcomposeApp/build.gradle.kts.Удалите зависимости
androidMain, поскольку весь код перемещен в модуль приложения: удалите блокkotlin.sourceSets.androidMain.dependencies {}.Убедитесь, что приложение Android работает как ожидалось.
(Необязательно) Разделение общей логики и общего пользовательского интерфейса
Если некоторые целевые платформы проекта используют нативный пользовательский интерфейс, возможно, стоит разделить общий код на модули sharedLogic и sharedUI, чтобы модулям приложений с нативным пользовательским интерфейсом не требовалась зависимость от Compose Multiplatform для использования общего кода.
Ниже на примере того же приложения показан возможный подход.
Создание модуля общей логики
Прежде чем создавать модуль, определите, что относится к бизнес-логике, то есть какой код не зависит ни от пользовательского интерфейса, ни от платформы. В этом примере единственный подходящий вариант — функция currentTimeAt(), которая возвращает точное время для пары «местоположение и часовой пояс». Напротив, класс данных Country зависит от DrawableResource из Compose Multiplatform и не может быть отделен от кода пользовательского интерфейса.
Вынесите соответствующий код в модуль sharedLogic:
Создайте каталог
sharedLogicв корне проекта.В этом каталоге создайте пустой файл
build.gradle.ktsи каталогsrc.-
Добавьте новый модуль в
settings.gradle.kts, добавив эту строку в конец файла:include(":sharedLogic") -
Настройте сценарий сборки Gradle для нового модуля.
-
Добавьте плагин библиотеки Android-KMP в каталог версий в файле
gradle/libs.versions.toml:[plugins] androidMultiplatformLibrary = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" } -
Укажите плагины, необходимые модулю общей логики, в файле
sharedLogic/build.gradle.kts:plugins { alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.androidMultiplatformLibrary) } -
Убедитесь, что эти плагины указаны в файле
build.gradle.ktsв корневом каталоге:plugins { alias(libs.plugins.androidMultiplatformLibrary) apply false alias(libs.plugins.kotlinMultiplatform) apply false // ... } -
Укажите в файле
sharedLogic/build.gradle.ktsцелевые платформы, которые должен поддерживать общий модуль в этом примере:kotlin { // There's no need for iOS framework configuration since sharedLogic // is not going to be exported as a framework, only 'sharedUI' is. iosArm64() iosSimulatorArm64() jvm() js { browser() } @OptIn(ExperimentalWasmDsl::class) wasmJs { browser() } } -
Для Android вместо блока
androidTarget {}добавьте конфигурациюandroidLibrary {}в блокkotlin {}:kotlin { // ... androidLibrary { namespace = "com.jetbrains.greeting.demo.sharedLogic" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() compilerOptions { jvmTarget = JvmTarget.JVM_11 } } } -
Добавьте необходимые зависимости для работы со временем в наборы исходного кода common и JavaScript так же, как они объявлены для
composeApp:kotlin { sourceSets { commonMain.dependencies { implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0") } webMain.dependencies { implementation(npm("@js-joda/timezone", "2.22.0")) } } } В главном меню выберите Сборка | Синхронизировать проект с файлами Gradle или нажмите кнопку обновления Gradle в редакторе.
-
-
Переместите бизнес-логику, выделенную на первом шаге:
Создайте каталог
commonMain/kotlinвнутриsharedLogic/src.Создайте файл
CurrentTime.ktвнутриcommonMain/kotlin.Переместите функцию
currentTimeAtиз исходного файлаApp.ktвCurrentTime.kt.
-
Сделайте функцию доступной компонуемой функции
App()по новому адресу. Для этого объявите зависимость междуcomposeAppиsharedLogicв файлеcomposeApp/build.gradle.kts:commonMain.dependencies { implementation(projects.sharedLogic) } Еще раз выполните Сборка | Синхронизировать проект с файлами Gradle, чтобы применить изменения.
Импортируйте функцию
currentTimeAt()в файлcomposeApp/commonMain/.../App.kt, чтобы исправить код.Запустите приложение, чтобы убедиться, что новый модуль работает правильно.
Вы успешно вынесли общую логику в отдельный модуль и использовали ее на разных платформах. Следующий шаг — создание модуля общего пользовательского интерфейса.
Создание модуля общего пользовательского интерфейса
Вынесите общий код, реализующий общие элементы пользовательского интерфейса, в модуль sharedUI:
Создайте каталог
sharedUIв корне проекта.В этом каталоге создайте пустой файл
build.gradle.ktsи каталогsrc.-
Добавьте новый модуль в
settings.gradle.kts, добавив эту строку в конец файла:include(":sharedUI") -
Настройте сценарий сборки Gradle для нового модуля:
-
Если вы еще не сделали этого для модуля
sharedLogic, добавьте плагин библиотеки Android-KMP в каталог версий в файлеgradle/libs.versions.toml:[plugins] androidMultiplatformLibrary = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" } -
Укажите плагины, необходимые модулю общего пользовательского интерфейса, в файле
sharedUI/build.gradle.kts:plugins { alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.androidMultiplatformLibrary) alias(libs.plugins.composeMultiplatform) alias(libs.plugins.composeCompiler) } -
Убедитесь, что все эти плагины указаны в файле
build.gradle.ktsв корневом каталоге:plugins { alias(libs.plugins.androidMultiplatformLibrary) apply false alias(libs.plugins.composeMultiplatform) apply false alias(libs.plugins.composeCompiler) apply false alias(libs.plugins.kotlinMultiplatform) apply false // ... } -
Укажите в блоке
kotlin {}целевые платформы, которые должен поддерживать модуль общего пользовательского интерфейса в этом примере:kotlin { listOf( iosArm64(), iosSimulatorArm64() ).forEach { iosTarget -> iosTarget.binaries.framework { // This is the name of the iOS framework you're going // to import in your Swift code. baseName = "sharedUI" isStatic = true } } jvm() js { browser() binaries.executable() } @OptIn(ExperimentalWasmDsl::class) wasmJs { browser() binaries.executable() } } -
Для Android вместо блока
androidTarget {}добавьте конфигурациюandroidLibrary {}в блокkotlin {}:kotlin { // ... androidLibrary { namespace = "com.jetbrains.greeting.demo.sharedUI" compileSdk = libs.versions.android.compileSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt() compilerOptions { jvmTarget = JvmTarget.JVM_11 } // Enables Compose Multiplatform resources to be used in the Android app androidResources { enable = true } } } -
Добавьте необходимые зависимости для общего пользовательского интерфейса так же, как они объявлены для
composeApp:kotlin { sourceSets { commonMain.dependencies { implementation(projects.sharedLogic) implementation(compose.runtime) implementation(compose.foundation) implementation(compose.material3) implementation(compose.ui) implementation(compose.components.resources) implementation(compose.components.uiToolingPreview) implementation(libs.androidx.lifecycle.viewmodelCompose) implementation(libs.androidx.lifecycle.runtimeCompose) implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0") } } } В главном меню выберите Сборка | Синхронизировать проект с файлами Gradle или нажмите кнопку обновления Gradle в редакторе.
-
Создайте новый каталог
commonMain/kotlinвнутриsharedUI/src.Переместите файлы ресурсов в модуль
sharedUI: весь каталогcomposeApp/commonMain/composeResourcesнужно перенести вsharedUI/commonMain/composeResources.Создайте новый файл
App.ktвsharedUI/src/commonMain/kotlin directory.Скопируйте все содержимое исходного файла
composeApp/src/commonMain/.../App.ktв новый файлApp.kt.Временно закомментируйте весь код в старом файле
App.kt. Это позволит проверить работу модуля общего пользовательского интерфейса, прежде чем полностью удалить старый код.-
Новый файл
App.ktдолжен работать как ожидалось, за исключением импортов ресурсов, которые теперь находятся в другом пакете. Повторно импортируйте объектResи все drawable-ресурсы, указав правильный путь, например:import demo.composeapp.generated.resources.mximport demo.sharedui.generated.resources.mx -
Чтобы новая компонуемая функция
App()стала доступна точкам входа модулей приложения, которые от нее зависят, добавьте зависимость в соответствующие файлыbuild.gradle.kts:kotlin { sourceSets { commonMain.dependencies { implementation(projects.sharedUI) // ... } } } Запустите приложения, чтобы убедиться, что новый модуль предоставляет точкам входа приложений общий код пользовательского интерфейса.
Удалите файл
composeApp/src/commonMain/.../App.kt.
Вы успешно переместили кроссплатформенный код пользовательского интерфейса в отдельный модуль.
Обновление интеграции с iOS
Поскольку точка входа приложения iOS не собирается как отдельный модуль Gradle, исходный код можно встроить в любой модуль. В этом примере его можно оставить внутри shared:
Переместите каталог
composeApp/src/iosMainв каталогshared/src.-
Настройте проект Xcode для использования фреймворка, созданного модулем
shared:Выберите пункт меню Файл | Открыть проект в Xcode.
Нажмите проект iosApp в окне инструментов Навигатор проекта, затем выберите вкладку Этапы сборки.
Найдите этап Компиляция фреймворка Kotlin.
-
Найдите строку, начинающуюся с
./gradlew, и заменитеcomposeAppнаsharedUi:./gradlew :shared:embedAndSignAppleFrameworkForXcode
Обратите внимание, что импорт в файле
ContentView.swiftдолжен остаться без изменений, поскольку он соответствует параметруbaseNameиз конфигурации Gradle для целевой платформы iOS, а не фактическому имени модуля. Если вы измените имя фреймворка в файлеshared/build.gradle.kts, необходимо соответствующим образом изменить директиву импорта.
Запустите приложение из Xcode или с помощью конфигурации запуска iosApp в IntelliJ IDEA.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/multiplatform/multiplatform-project-recommended-structure.html