Kotlin Multiplatform Development Help

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.

Use Compose Multiplatform inside a UIKit application

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:

UIKit

Explore this code in the sample project.

Use UIKit inside Compose Multiplatform

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:

MapView

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.

What's next

You can also explore the way Compose Multiplatform can be integrated with the SwiftUI framework.

Last modified: 14 March 2024