Интеграция с фреймворком SwiftUI
Compose Multiplatform совместим с фреймворком SwiftUI. Вы можете встроить Compose Multiplatform в приложение SwiftUI, а также встроить собственные компоненты SwiftUI в пользовательский интерфейс Compose Multiplatform. На этой странице приведены примеры использования Compose Multiplatform внутри SwiftUI и встраивания SwiftUI в приложение Compose Multiplatform.
Использование Compose Multiplatform в приложении SwiftUI
Чтобы использовать Compose Multiplatform в приложении SwiftUI, создайте функцию Kotlin MainViewController(), которая возвращает UIViewController из UIKit и содержит код Compose Multiplatform:
fun MainViewController(): UIViewController =
ComposeUIViewController {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text("This is Compose code", fontSize = 20.sp)
}
}
ComposeUIViewController() — это библиотечная функция Compose Multiplatform, которая принимает компонуемую функцию в качестве аргумента content. Переданная таким образом функция может вызывать другие компонуемые функции, например Text().
Затем понадобится структура, представляющая Compose Multiplatform в SwiftUI. Создайте следующую структуру, преобразующую экземпляр UIViewController в представление SwiftUI:
struct ComposeViewController: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
return Main_iosKt.MainViewController()
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
}
}
Теперь вы можете использовать структуру ComposeView в другом коде SwiftUI.
Main_iosKt.MainViewController — это сгенерированное имя. Подробнее о доступе к коду Kotlin из Swift см. на странице Взаимодействие со Swift/Objective-C.
В итоге приложение должно выглядеть так:

Вы можете использовать этот компонент ComposeView в любой иерархии представлений SwiftUI и управлять его размером из кода SwiftUI.
Чтобы встроить Compose Multiplatform в существующие приложения, используйте структуру ComposeView везде, где используется SwiftUI. Пример см. в нашем примерном проекте.
Использование SwiftUI в Compose Multiplatform
Чтобы использовать SwiftUI в Compose Multiplatform, добавьте код Swift в промежуточный компонент UIViewController. Сейчас нельзя объявлять структуры SwiftUI напрямую в Kotlin. Вместо этого их нужно написать на Swift и передать функции Kotlin.
Для начала добавьте аргумент в функцию точки входа, чтобы создать компонент ComposeUIViewController:
@OptIn(ExperimentalForeignApi::class)
fun ComposeEntryPointWithUIViewController(
createUIViewController: () -> UIViewController
): UIViewController =
ComposeUIViewController {
Column(
Modifier
.fillMaxSize()
.windowInsetsPadding(WindowInsets.systemBars),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("How to use SwiftUI inside Compose Multiplatform")
UIKitViewController(
factory = createUIViewController,
modifier = Modifier.size(300.dp).border(2.dp, Color.Blue),
)
}
}
В коде Swift передайте createUIViewController в функцию точки входа. Для обёртывания представлений SwiftUI можно использовать экземпляр UIHostingController:
Main_iosKt.ComposeEntryPointWithUIViewController(createUIViewController: { () -> UIViewController in
let swiftUIView = VStack {
Text("SwiftUI in Compose Multiplatform")
}
return UIHostingController(rootView: swiftUIView)
})
В итоге приложение должно выглядеть так:

Изучите код этого примера в примерном проекте.
Представление карты
В Compose Multiplatform можно реализовать представление карты с помощью компонента SwiftUI Map. Это позволяет отображать в приложении полностью интерактивные карты SwiftUI.
Для той же функции точки входа Kotlin передайте в Swift UIViewController, оборачивающий представление Map с помощью UIHostingController:
import SwiftUI
import MapKit
Main_iosKt.ComposeEntryPointWithUIViewController(createUIViewController: {
let region = Binding.constant(
MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194),
span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
)
)
let mapView = Map(coordinateRegion: region)
return UIHostingController(rootView: mapView)
})
Теперь рассмотрим более сложный пример. Этот код добавляет к карте SwiftUI пользовательскую аннотацию и позволяет обновлять состояние представления из Swift:
import SwiftUI
import MapKit
struct AnnotatedMapView: View {
// Manages map region state
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 51.5074, longitude: -0.1278),
span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
)
// Displays a map with a custom annotation
var body: some View {
Map(coordinateRegion: $region, annotationItems: [Landmark.example]) { landmark in
MapMarker(coordinate: landmark.coordinate, tint: .blue)
}
}
}
struct Landmark: Identifiable {
let id = UUID()
let name: String
let coordinate: CLLocationCoordinate2D
static let example = Landmark(
name: "Big Ben",
coordinate: CLLocationCoordinate2D(latitude: 51.5007, longitude: -0.1246)
)
}
Затем можно обернуть эту карту с аннотацией в UIHostingController и передать её коду Compose Multiplatform:
Main_iosKt.ComposeEntryPointWithUIViewController(createUIViewController: {
return UIHostingController(rootView: AnnotatedMapView())
})
AnnotatedMapView выполняет следующие задачи:
Определяет представление SwiftUI
Mapи встраивает его в пользовательское представление под названиемAnnotatedMapView.Управляет внутренним состоянием положения карты с помощью
@StateиMKCoordinateRegion, позволяя Compose Multiplatform отображать интерактивную карту с учётом состояния.Отображает на карте
MapMarkerс помощью статической моделиLandmark, соответствующейIdentifiable, что необходимо для аннотаций в SwiftUI.Использует
annotationItemsдля декларативного размещения пользовательских маркеров на карте.Оборачивает компонент SwiftUI в
UIHostingController, который затем передаётся в Compose Multiplatform какUIViewController.
Представление камеры
В Compose Multiplatform можно реализовать представление камеры с помощью SwiftUI и компонента UIKit UIImagePickerController, обёрнутого в совместимый со SwiftUI компонент. Это позволяет запускать системную камеру и делать снимки.
Для той же функции точки входа Kotlin определите в Swift простое CameraView с помощью UIImagePickerController и встроите его с помощью UIHostingController:
Main_iosKt.ComposeEntryPointWithUIViewController(createUIViewController: {
return UIHostingController(rootView: CameraView { image in
// Handle captured image here
})
})
Чтобы это работало, определите CameraView следующим образом:
import SwiftUI
import UIKit
struct CameraView: UIViewControllerRepresentable {
let imageHandler: (UIImage) -> Void
@Environment(\.presentationMode) private var presentationMode
init(imageHandler: @escaping (UIImage) -> Void) {
self.imageHandler = imageHandler
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.sourceType = .camera
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
let parent: CameraView
init(_ parent: CameraView) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[.originalImage] as? UIImage {
parent.imageHandler(image)
}
parent.presentationMode.wrappedValue.dismiss()
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
parent.presentationMode.wrappedValue.dismiss()
}
}
}
Теперь рассмотрим более сложный пример. Этот код показывает представление камеры и отображает миниатюру сделанного снимка в том же представлении SwiftUI:
import SwiftUI
import UIKit
struct CameraPreview: View {
// Controls the camera sheet visibility
@State private var showCamera = false
// Stores the captured image
@State private var capturedImage: UIImage?
var body: some View {
VStack {
if let image = capturedImage {
// Displays the captured image
Image(uiImage: image)
.resizable()
.scaledToFit()
.frame(height: 200)
} else {
// Shows placeholder text when no image is captured
Text("No image captured")
}
// Adds a button to open the camera
Button("Open Camera") {
showCamera = true
}
// Presents CameraView as a modal sheet
.sheet(isPresented: $showCamera) {
CameraView { image in
capturedImage = image
}
}
}
}
}
Представление CameraPreview выполняет следующие задачи:
Показывает
CameraViewв модальном.sheet, когда пользователь нажимает кнопку.Использует обёртку свойства
@Stateдля хранения и отображения сделанного снимка.Встраивает собственное представление SwiftUI
Imageдля предварительного просмотра снимка.Повторно использует то же
UIViewControllerRepresentable-basedCameraView, что и ранее, но теснее интегрирует его с системой состояния SwiftUI.
Веб-представление
В Compose Multiplatform можно реализовать веб-представление с помощью SwiftUI, обернув компонент UIKit WKWebView в UIViewRepresentable. Это позволяет отображать встроенный веб-контент с полноценным нативным рендерингом.
Для той же функции точки входа Kotlin определите в Swift простое WebView, встроенное с помощью UIHostingController:
Main_iosKt.ComposeEntryPointWithUIViewController(createUIViewController: {
let url = URL(string: "https://www.jetbrains.com")!
return UIHostingController(rootView: WebView(url: url))
})
Теперь рассмотрим более сложный пример. Этот код добавляет в веб-представление отслеживание переходов и отображение состояния загрузки:
import SwiftUI
import UIKit
import WebKit
struct AdvancedWebView: UIViewRepresentable {
let url: URL
@Binding var isLoading: Bool
@Binding var currentURL: String
// Creates WKWebView with navigation delegate
func makeUIView(context: Context) -> WKWebView {
let webView = WKWebView()
webView.navigationDelegate = context.coordinator
webView.load(URLRequest(url: url))
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {}
// Creates coordinator to handle web navigation events
func makeCoordinator() -> Coordinator {
Coordinator(isLoading: $isLoading, currentURL: $currentURL)
}
class Coordinator: NSObject, WKNavigationDelegate {
@Binding var isLoading: Bool
@Binding var currentURL: String
init(isLoading: Binding<Bool>, currentURL: Binding<String>) {
_isLoading = isLoading
_currentURL = currentURL
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation?) {
isLoading = true
}
// Updates URL and indicates loading has completed
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation?) {
isLoading = false
currentURL = webView.url?.absoluteString ?? ""
}
}
}
Используйте его в представлении SwiftUI следующим образом:
struct WebViewContainer: View {
// Tracks loading state of web view
@State private var isLoading = false
// Tracks current URL displayed
@State private var currentURL = ""
var body: some View {
VStack {
// Displays loading indicator while loading
if isLoading {
ProgressView()
}
// Shows current URL
Text("URL: \(currentURL)")
.font(.caption)
.lineLimit(1)
.truncationMode(.middle)
// Embeds the advanced web view
AdvancedWebView(
url: URL(string: "https://www.jetbrains.com")!,
isLoading: $isLoading,
currentURL: $currentURL
)
}
}
}
AdvancedWebView и WebViewContainer выполняют следующие задачи:
Создают
WKWebViewс пользовательским делегатом навигации для отслеживания хода загрузки и изменений URL.Используют привязки SwiftUI
@Stateдля динамического обновления пользовательского интерфейса в ответ на события навигации.Показывают индикатор
ProgressViewво время загрузки страницы.Отображают текущий URL в верхней части представления с помощью компонента
Text.Используют
UIHostingControllerдля интеграции этого компонента в пользовательский интерфейс Compose.
Что дальше
Узнайте, как использовать собственную навигацию SwiftUI для системных эффектов Liquid Glass, пока Compose отображает содержимое экрана.
Узнайте, как можно интегрировать Compose Multiplatform с фреймворком UIKit.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/multiplatform/compose-swiftui-integration.html