Experimenting Kotlin Multiplatform

Cross-platform experimentation series

Thongchai Kolyutsakul
Viki Blog

--

We experimented using Kotlin Multiplatform to share code such as data model, networking, parsing, and business logic. Here are my thoughts about the technology.

Kotlin Multiplatform is an experimental language feature that allows compiling code multiple platforms. A main building block of it is Kotlin/Native, which is a technology for compiling Kotlin code to native binaries. This allows us to call native APIs from Kotlin side.

Check out these resources on how it works:

And some blog posts of what people think after experimenting it:

There is a very useful multiplatform template with Cocoapods setup in iOS and backend support. Setting up the project is not easy so this should be very helpful.

Our experience so far…

The Technology state

TLDR; Should I use in production? — Not yet. ❌

There’s a warning in Kotlin website saying “Multiplatform is an experimental feature”. This means things can change in the future. Kotlin/Native github also note in readme file that it is in beta version.

Also, regarding performance, as noted in Kotlin/Native repo readme

*** DO NOT USE THIS PREVIEW RELEASE FOR ANY PERFORMANCE ANALYSIS ***

This beta version of Kotlin/Native technology is not yet tuned for benchmarking and competitive analysis of any kind.

Maintainability

Kotlin Multiplatform provides a good code sharing interface. You share as much code as needed. The parts you don’t want to share, you can call platform specific APIs through expect/actual mechanism. This makes the code more adaptive to new requirements, thus more maintainable.

For developers coming from iOS background, they should be able to pick up Kotlin in no time because Swift is pretty much like Kotlin. Having an iOS developer maintaining a Kotlin Multiplatform project should not be difficult.

Setting up the project

I followed this Raywenderlich tutorial on how to build a framework that shares model layer, network layer, and JSON parsing for iOS and Android. These layers are pretty much the same on all platforms. (The article is still missing some steps near the end. You can look at their final completed project file if you need help.

The initial setup feels a little troublesome on the iOS side. For example, I still have to manually switch architecture for compilation on different devices. (iOS simulator and devices use different architectures.) I also need to add a “Run script” build phase in Xcode to copy the framework over.

Device architecture branching for iOS (From Raywenderlich)

You will also need to learn how Gradle works. It is used extensively to configure all the modules together.

Interoperability

Kotlin/Native provides bi-directional interoperability with Objective-C/Swift. Objective-C frameworks and libraries can be used in Kotlin code. Kotlin modules can be used in Swift/Objective-C code too.

The first thing I check is how Kotlin function type parameters look like in Swift. A function with function type parameter like this in Kotlin…

is translated to this Objective-C header…

and looks like this at the call site in Swift…

Notice that you need to return KotlinUnit() in success/failure closure because it hasUnit return type in Kotlin. ( Unit acts like void with less technical limitation.) This can cause some noise in the code.

Another thing I tested is Kotlin Int type. It turns into int32_t in Objective-C and Int32 in Swift.

Swift collection types translation are quite direct…

You can read more at this Kotlin/Native as an Apple Framework article.

Result type

I usually use Result<T> generic type in Swift to wrap asynchronous API function calls. It’s generally considered a good pattern and it is included in Swift 5.

Result type uses Generics. However, translating Kotlin generics to Swift generics is not supported yet. This means we cannot implement Result type, at least how we do it in Swift.

K/N (Kotlin/Native) does not interop with Swift directly yet, only via Objective-C, thus this feature request is not something we could help with at the moment. — a Kotlin/Native Github issue

Kotlin 1.3 introduced Result type (as an experimental feature, disabled by default). But there’s a slight difference from iOS. Instead of an enum, it is a class. So it’s a really fresh concept for Android. If this gets more adoption, there will be slight difference in how Result type works in iOS and Android.

At this point, I’m not sure how to gracefully support both. One option is we can create an expect interface for Result type in our common code. If not, we can just create our own Result type in Kotlin and use whatever it is translated into in Swift.

Conclusion

I think Kotlin Multiplatform has a good strategy of how code sharing should work. You share only what you need. Apps would still feel native. The maintainability is there. I wish primitive type conversion is more straightforward and generics are supported. Unfortunately, until Kotlin Multiplatform goes out of beta, we have to put it in a keep-in-view state.

Resources

--

--

iOS developer since 2009. Working @Viki in Singapore. I write about iOS development, Swift language, and general software engineers tips.