Integration with the UIKit framework
Compose Multiplatform is interoperable with the UIKit framework. You can embed Compose Multiplatform within an UIKit application as well as embed native UIKit components within Compose Multiplatform. This page provides examples both for using Compose Multiplatform inside a UIKit application and for embedding UIKit components inside Compose Multiplatform UI.
tip
To learn about SwiftUI interoperability, see the Integration with the SwiftUI framework article.
To use Compose Multiplatform inside a UIKit application, add your Compose Multiplatform code to any container view controller. This example uses Compose Multiplatform inside the UITabBarController
class:
let composeViewController = Main_iosKt.ComposeOnly()
composeViewController.title = "Compose Multiplatform inside UIKit"
let anotherViewController = UIKitViewController()
anotherViewController.title = "UIKit"
// Set up the UITabBarController
let tabBarController = UITabBarController()
tabBarController.viewControllers = [
// Wrap the created ViewControllers in a UINavigationController to set titles
UINavigationController(rootViewController: composeViewController),
UINavigationController(rootViewController: anotherViewController)
]
tabBarController.tabBar.items?[0].title = "Compose"
tabBarController.tabBar.items?[1].title = "UIKit"
With this code, your application should look like this:

Explore this code in the sample project.
To use UIKit elements inside Compose Multiplatform, add the UIKit elements that you want to use to a UIKitView from Compose Multiplatform. You can write this code purely in Kotlin or use Swift as well.
In this example, UIKit's MKMapView
component is displayed in Compose Multiplatform. Set the component size by using the Modifier.size()
or Modifier.fillMaxSize()
functions from Compose Multiplatform:
UIKitView(
factory = { MKMapView() },
modifier = Modifier.size(300.dp),
)
With this code, your application should look like this:

Now, let's look at an advanced example. This code wraps UIKit's UITextField
in Compose Multiplatform:
@OptIn(ExperimentalForeignApi::class)
@Composable
fun UseUITextField(modifier: Modifier = Modifier) {
var message by remember { mutableStateOf("Hello, World!") }
UIKitView(
factory = {
val textField = object : UITextField(CGRectMake(0.0, 0.0, 0.0, 0.0)) {
@ObjCAction
fun editingChanged() {
message = text ?: ""
}
}
textField.addTarget(
target = textField,
action = NSSelectorFromString(textField::editingChanged.name),
forControlEvents = UIControlEventEditingChanged
)
textField
},
modifier = modifier.fillMaxWidth().height(30.dp),
update = { textField ->
textField.text = message
}
)
}
The factory parameter contains the editingChanged()
function and the textField.addTarget()
listener to detect any changes to UITextField
. The editingChanged()
function is annotated with @ObjCAction
so that it can interoperate with Objective-C code. The action
parameter of the addTarget()
function later on passes the name of the editingChanged()
function, so it would be called in response to a UIControlEventEditingChanged
event.
The update
parameter of UIKitView()
is called when the observable message state changes its value:
update = { textField ->
textField.text = message
}
The function updates the text
attribute of the UITextField
so that the user sees the updated value.
Explore the code for this example in this sample project.
You can also explore the way Compose Multiplatform can be integrated with the SwiftUI framework.
Thanks for your feedback!