Targeting Kotlin for both Android and iOS

Jitin Sharma
ProAndroidDev
Published in
4 min readMar 21, 2018

--

Kotlin has been traditionally used as a language for JVM based platforms and has become highly popular in Android ecosystem. As the language matures, it is knocking on new frontiers — platforms other than JVM, one of them being iOS.

Kotlin started out with compilation to .class files which allowed interoperability with Java and conversion to .dex for Android. But now with Kotlin Native, kotlin can target platforms which directly execute bytecode without a VM — emebedded systems, macOS and iOS.

Let’s look at an example

Above is a simple piece of code with multiple classes and variables written in kotlin. Important thing to note is that it is not importing any library except for kotlin-stdlib

And here is a build.gradle for compiling this code into a jar

Now we’ll compile this to a .jar using ./gradlew assemble and then import this to an Android Project.

Classes Generated

We can see three class files generated from Base.kt

  • BaseKt.class — For constant API_KEY variable
  • Helper and Model both of which are seperate classes

Now we can simple call this code in an Activity in a very straightforward way

Moving to iOS

Let’s see if we can reproduce similar approach for iOS using Kotlin Native plugin.

In a folder above our Base project, we’ll add following build.gradle

Few things to note

  • konan is the plugin for Kotlin Native which allows targeting kotlin code to multiple platforms
  • konan.targets specify for which targets bytecode must be generated. We can also add other platform like raspberry pi to it.
  • konanArtifacts will specify artifacts to be generated along with their name and src directory if required.

We will run ./gradlew build on this which will produce the following

Objective C framework created after build

We now have a file named Base.framework which is an iOS framework file and can be directly imported to Xcode. Let’s do that!

Link framework file to a project

We have received something called Base.h from the framework which contains code converted from Base.kt .

Header files are a little complex to read but Xcode provides Swift conversion of such files for better understanding. Here is an excerpt of what is present in header file

  • By default a class named KotlinBase is created which extends NSObject and also implements NSCopying and all other classes extend this class.
  • All classes have prefix “Base” which is the name we provided in build.gradle while creating the iOS framework
  • Int from Kotlin is converted to Int32 in Swift not Int(Swift).
  • Kotlin’s List<T> is converted to a Swift Array.
  • Companion object is converted to a separate class with an init() method.
  • Module level constant API_KEY is converted to an function within a class.
  • BaseModel which is derived from a data class has a function doCopy similar to copy() of data class. But default initialization or copy is not possible as all arguments must be specified while initializing or copying.

Now let’s try to call these functions from a Swift file

So we took a piece of raw Kotlin code and ran it on multiple platforms without actually changing anything on the platform side code. Although above code may not be useful for production level applications, but in future as Kotlin Native and Kotlin Mutliplatform gets mature, we should be able to move more logic towards a common project.

Kotlinx Serialization is a library built on this concept and supports JVM/JS for now with native support coming soon. With this we should be able to serialize/deserialize data classes to JSON on all platforms with single lib.

Full code here

Thanks for reading!

--

--