Bringing Together: Jetpack Compose and Native iOS Components

Chetansinh Rajput
Mobile Innovation Network
3 min readMay 29, 2024

Compose Multiplatform for iOS is now in Beta, boasting significantly improved performance that feels more natural and fluid. Who knew coding could feel like a smooth jazz sax solo? One of the standout features of Jetpack Compose is its seamless interoperability with native iOS components like UIKit and SwiftUI, making the development process more efficient and enjoyable. It’s like adding rocket boosters to your coding experience!

Let’s take a closer look at how you can use Jetpack Compose components in iOS and integrate iOS native components into your Compose code. Because who doesn’t love mixing and matching tech like a master chef?

Integrating Compose into iOS Native

Integrating Jetpack Compose elements within an iOS project is straightforward. You can embed Compose UI components directly within SwiftUI or UIKit views, enabling you to gradually introduce Compose into your existing iOS applications without a complete rewrite.

  1. Setup: First, ensure you have the necessary dependencies and setup in your project to support Compose Multiplatform.
  2. Create Compose UI: Design your UI using Jetpack Compose as you normally would in an Android project.
  3. Embed in UIKit/SwiftUI: Use the interoperability features to embed your Compose UI within native iOS views. This could involve wrapping Compose components in a UIViewController for UIKit or a UIViewControllerRepresentable for SwiftUI.

Example

Here’s a simple example of how you might embed a Compose component within a SwiftUI view:

To use Jetpack Compose elements in an iOS application, you first need to convert them into a `UIViewController`. By utilizing `ComposeUIViewController`, you can make Compose elements compatible with iOS.

fun VideoController(url: String): UIViewController = ComposeUIViewController {
VideoPlayer(url)
}

@Composable
fun VideoPlayer(
url: String
) {
// Video player code
}

Jetpack Compose automatically converts its elements into `UIViewController`, which can be directly utilized in Swift. However, when integrating these components into SwiftUI, you need to employ `UIViewControllerRepresentable` to seamlessly incorporate Compose elements within your SwiftUI views.

struct ContentView: View {
var body: some View {
ComposeView()
}
}

struct ComposeView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
// Call the Kotlin ViewController
VideoController(url: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
}

func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}

Bingo! You’ve successfully integrated Jetpack Compose components into your native iOS project, seamlessly bridging the gap between platforms.

Bringing iOS Native Components into Compose

By leveraging `UIKitView` and `UIKitViewController`, we seamlessly integrate Jetpack Compose elements into native iOS components. Let’s delve deeper into this process with an example of integrating a video player component. Cue the dramatic music as we unveil the magic of coding fusion!

fun VideoController(url: String): UIViewController = ComposeUIViewController {
VideoPlayer(url)
}

@OptIn(ExperimentalForeignApi::class)
@Composable
fun VideoPlayer(
url: String
) {
val urlObject = NSURL.URLWithString(url) ?: return
val playerItem = AVPlayerItem(uRL = urlObject)
val player: AVQueuePlayer by remember { mutableStateOf(AVQueuePlayer(playerItem)) }
val playerLayer by remember { mutableStateOf(AVPlayerLayer()) }
val avPlayerViewController = remember { AVPlayerViewController() }
avPlayerViewController.player = player
avPlayerViewController.videoGravity = AVLayerVideoGravityResizeAspectFill
val playerContainer = UIView().apply {
layer.addSublayer(playerLayer)
}

Box {
UIKitView(
factory = {
playerContainer.addSubview(avPlayerViewController.view)
playerContainer
},
onResize = { view: UIView, rect: CValue<CGRect> ->
CATransaction.begin()
CATransaction.setValue(true, kCATransactionDisableActions)
view.layer.setFrame(rect)
playerLayer.setFrame(rect)
avPlayerViewController.view.layer.frame = rect
CATransaction.commit()
},
update = { _ ->
player.play()
},
interactive = false,
modifier = Modifier.fillMaxSize()
)
}
}

In this example, the UIKitView function allows us to seamlessly integrate the native iOS AVPlayerViewController into our Compose UI. We create the necessary iOS objects such as NSURL, AVPlayerItem, and AVQueuePlayer within the Compose function. Then, using the UIKitView function, we embed the player view within our Compose layout.

Conclusion

The integration of Jetpack Compose elements into native iOS components opens up exciting possibilities for cross-platform development. Through the seamless interoperability provided by `UIKitView` and `UIKitViewController`, developers can create rich and engaging user experiences that leverage the strengths of both platforms. So go ahead, mix, match, and code like a boss!

Connect with us 👇

Linkedin

GitHub

--

--