Kotlin Multiplatform as iOS Developer

Photo of Sebastian Grabiński

Sebastian Grabiński

Updated Jan 9, 2023 • 7 min read
apple-devices-art-blur-347696

Debate about „cross-platform vs native” rages lastly due to Google’s Flutter. Google is trying to revolutionize mobile development, in the meantime, JetBrains is slowly trying to develop some „worth to consider" solution.

Let’s be honest, Java is popular... very popular and in the future, Kotlin can be the next big thing, as the popularity is expected to grow as it is now. According to Stack Overflow's 2018 Annual Developer Survey Kotlin is the second beloved language among Developers.

Kotlin Multiplatform?

Kotlin Multiplatform puts together all the hard work done by JetBrains to allow compilation of Kotlin to three different targets: JS, JVM and Native being three separate projects that you could use separately as well. Kotlin Native is one of them and it's basically a solution for compiling Kotlin code to native binaries. Primarily it is designed to allow compilation without any virtual machine. At the moment target platforms are:

  • iOS
  • MacOS
  • Android
  • Windows
  • Linux
  • WebAssembly

It means our business logic could be written once and shared natively on all of those platforms. Nice!

null

Cross-platform

When deciding about native or cross-platform development, there are a few things we must consider. First of all money and time - these are the most important things from the business perspective. As we all know cross-platform apps are cheaper and faster to create. Shared code between platforms seems to be a great idea, but … is it always so great ?

Here comes the second thing - technology.

We have Xamarin that compiles to CIL and React Native which is basically JS. With both of them, we have additional abstraction above the UI layer. We are also running a code that might not be the most performant on given platform. JS will have to run on V8/JavaScriptCore and then communicate with native code through some bridge. Same would happen for Xamarin that would use ACW and MCW to wrap native calls (mechanism similar to JNI) on Android.

Kotlin Multiplatform compiles to multiple targets, giving us native binaries where we want them - iOS or JVM bytecode output - e.g. Android.

Also, we are using standard components made for UI building, so we can completely separate and differ UIs for both platforms.

Let’s look at our Kotlin Multiplatform Storage as an example (Made in Kotlin Multiplatform). You can read more about creating it here

We wanted to create secure keychain wrapper for both platforms, so I guess UserDefaults wasn't the best place for this kind of data. Firstly we tried to implement Keychain fully written in Kotlin, what at the end seemed to be impossible, due to lack of Objective-C casting. After many tries, we finally decided that we will use c-interop tool, for created native library and connect it into Kotlin App. So what we did, was basically creating Objective-C library, that will create Kotlin Interface from linked framework, so we can use it in the Swift app! Yeah… I know - Cross-platform...

Right now it is hard to tell if any of these could be done better. This technology is still very experimental, no documentation, no tutorials, no Stack Overflow topics.

Kotlin Multiplatform?

We have two types of modules - platform-specific and common.

Platform-specific module defines view and implements code from the common one.

The common main module is the one that keeps all the common part of the project. The code placed in this module is shared between every declared platform. However, it has some limitations, because you cannot access platform-specific features here. Instead, common main module can define a common interface for those features using expect/actual mechanism. So, this a good place to implement common business logic!

Platform package (e.g. androidMain) is a code that depends on the platform. For example framework implementation for the platform.

null

Implementation

So here is an example of the module for the iOS platform

Simply to make use of shared code base, you have to implement interface in your Swift class. In this example, we will have MainView interface

Kotlin
interface MainView {

    fun showElementAddedInfo()
    
    fun showToDoList(toDoList: List<String>)
}

Swift

final class MainViewController: UIViewController, MainView { }

Interface provides you methods that are used in Kotlin. So this is how Swift „delegates” Kotlin methods. And how it works in the other way?

We simply need to create instance of Presenter written in Kotlin so we can use methods created there.

Kotlin

class MainPresenter {
    fun foo() {
        print(„bar")
    }
}

Swift

private lazy var presenter: MainPresenter = {
    MainPresenter()
}()

func bar() {
    presenter.foo()
}

Another thing, which we can’t forget is attaching and detaching Views

We should attach view on the creation of ViewController instance. Without it, Kotlin code cannot be called properly.

presenter.attachView(view: self)

attachView is creating strong reference to passed object, so to release object we have to simply call

deinit {
    presenter.detachView()
}

Kotlin

fun detachView() {
    this.view = null
}

After all, we don’t need much to make use of the shared code base, but above we have scenario when the whole environment is already set up. So you will have to import generated framework, change Framework Search Paths in build settings, and call scripts. If you want to give it a try you should check this out

Conclusion

As the iOS Dev, you can read Kotlin code without any problem just at the first sight. Syntax similarity for smaller snippets can be more than 60%, so it wasn’t a problem to read and write code in Kotlin (there are even ready to use converters like this one ). Probably if not the annotations above the code snippets, it would be hard to tell which code is written in Swift or Kotlin. But the sad part is you still need to know how to create views on other platforms, so at least minimum knowledge about platform specific UI building is a must. Furthermore, solutions like Kotlin Native can be the future, one code base, and a lot of targets, including backend, frontend, mobile, and even embedded! Right now this technology is very experimental, and not production ready yet, but we will most likely hear much more about it in the future as there it is a lot of potential.

Photo of Sebastian Grabiński

More posts by this author

Sebastian Grabiński

Efficient software development  Build faster, deliver more  Start now!

Read more on our Blog

Check out the knowledge base collected and distilled by experienced professionals.

We're Netguru

At Netguru we specialize in designing, building, shipping and scaling beautiful, usable products with blazing-fast efficiency.

Let's talk business