Kotlin Multiplatform

Kotlin on iOS

Android Developer at Novoda

In our last blogpost we deep-dived into Kotlin’s multiplatform project feature and discussed how we can use it to build backend, Android and web applications written in Kotlin. Today we will investigate how we can add an iOS client to such a setup using Kotlin/Native and how easy that is.


Kotlin/Native is a tool that enables us to compile Kotlin code for platforms without a JVM or a JavaScript engine. In our example we will use it to build an Objective-C framework and integrate it into a XCode project.


Kotlin’s multiplatform projects use Gradle as build tool and JetBrains published a plugin for Kotlin/Native.

apply plugin: 'konan'

konan.targets = ['iphone', 'iphone_sim']

konanArtifacts {  
    framework('KotlinGameOfLife') {
        enableMultiplatform true

dependencies {  
    expectedBy project(':common')

Using the konanArtifacts closure we can specify the type of artefact we want the compiler to build. Besides many others it also supports framework, which will generate an Objective-C framework. Later on we will have a look how we can include such framework into an existing XCode project. Besides that, we also need to explicitly enable the multiplatform support. In similar fashion to the artefact we can specify a konan.target for a specific platform. By default the compiler will build the artefact just for the host, meaning the computer that is used for building.

As for any other platform module within a multiplatform project we also need to specify the dependency to the common module. The plugin generates a couple of tasks, in our example compileKonanKotlinGameOfLifeIphone and compileKonanKotlinGameOfLifeIphoneSim which will generate the Objective-C framework. So all we have to do is run gradle build on our multiplatform project to generate that artefact, which will be located in build/konan/bin.

Actual declarations for iOS

Our multiplatform project implements the Game of Life where the business logic and presentation layer live in the common module. Part of that is an expected class GameLoop which has an actual implementation for each platform.

interface GameLoop {

    var onTick: () -> Unit

    fun startWith(intervalMs: Int)

    fun stop()

    fun isLooping(): Boolean

expect class GameLoopImpl() : GameLoop  

Since our GameLoop requires some sort of asynchronicity the question is which API we can use to implement it on the Native side. The JVM implementation uses RxJava, while the Javascript version uses the window from the browser environment. For Kotlin/Native it might be tempting to look at Kotlin’s coroutines, but unfortunately these are not yet available on this platform. Another option would be to rely on a C library using Kotlin/Native’s interoperability feature. This feature analyses C headers and generates bindings that can be called from Kotlin. Luckily Kotlin/Native comes already with bindings for a few iOS libraries, for example the NSTimer. A list of all available bindings for iOS can be found here.

package com.novoda.gol

import platform.Foundation.*

actual class GameLoopImpl : GameLoop {

    private var timer: NSTimer? = null

    override var onTick: () -> Unit = {}

    override fun startWith(intervalMs: Int) {
        timer = NSTimer(NSDate(), 0.5, true, {
        NSRunLoop.currentRunLoop().addTimer(timer!!, NSRunLoopCommonModes)

    override fun stop() {
        timer = null

    override fun isLooping() = timer != null


The drawback of using interop is that we’re missing the usual level of IDE support; things like autocompletion are unavailable when using such bindings.

Integrate the generated Objective-C framework into XCode

This is fairly easy. Open XCode, select the tab General and click on + next to Embedded Libraries. In the chooser dialog select Add other and choose the generated framework which is located under build/konan/bin. That’s all. Next we can just import the framework into any Swift file and access your Kotlin code.

import UIKit  
import KotlinGameOfLife

class UICell: UIButton {

    let position:KGOLPositionEntity?

    init(frame: CGRect,position:KGOLPositionEntity) {
        self.position = position
        super.init(frame: frame)

    required init?(coder aDecoder: NSCoder) {
        self.position = nil
        super.init(coder: aDecoder)


Please note that the generated files are prefixed with your framework name, that has been specified in the build.gradle, as shown above. In this example KGOLPositionEntity is generated from PositionEntity.kt. The KGOL prefix we chose stands for Kotlin Game of Life.


Kotiln/Native finally adds support for targeting iOS and other platforms, which was previously missing from Kotlin’s featureset. The integration into an existing multiplatform project is fairly easy and will hopefully enable a lot of teams to share their code among the different mobile clients.

You can find our example project here on GitHub. If you have any question, don’t hesitate to contact me on twitter or get in touch with the JetBrains team using the official Kotlin Slack.

Enjoyed this article? There's more...

We send out a small, valuable newsletter with the best stories, app design & development resources every month.

No spam, no giving your data away, unsubscribe anytime.

About Novoda

We plan, design, and develop the world’s most desirable software products. Our team’s expertise helps brands like Sony, Motorola, Tesco, Channel4, BBC, and News Corp build fully customized Android devices or simply make their mobile experiences the best on the market. Since 2008, our full in-house teams work from London, Liverpool, Berlin, Barcelona, and NYC.

Let’s get in contact