Kotlin Multiplatform in Five Minutes or Less: Expect / Actuals Statements

Kotlin Multiplatform in Five Minutes or Less: Expect / Actuals Statements

If you’re reading this you’ve probably heard a lot about Kotlin Multiplatform, but aren’t sure where to start. The platform is evolving fast, which means a lot of the docs are out of date, and/or can be a little overwhelming. But nobody likes reading the directions, so I’m writing a series of posts that take about 5 minutes each to run through, and introduce the basics on Kotlin Multiplatform.

Part 1 gets you starting from nothing. This is part 2, which focuses on expect/actual statements. Kotlin’s native interop is one of its most distinguishing features. Unlike other “cross platform” ecosystems, Kotlin is designed to embrace the native platform it is integrating with. expect/actual statements are one of the main mechanisms it provides to do that.

One area that requires platform-specific logic is dealing with dates. We’re going to create a simple expect class, KMPDate, which takes a date format string and lets you create a formatted string representing today’s date.

First, open

/app/src/commonMain/kotlin/sample/Sample.kt. Underneath the Greeting class, create a new expect class:

expect class KMPDate(formatString: String) {
    fun asString(): String
}

The expect keyword declares that the common code can expect different actual implementations for each platform. In this case, expect applies to a class. However, it can also apply to functions, objects, annotations, etc. See here for more.

 

Go to /app/src/main/java/sample/SampleAndroid.kt to create the actualAndroid implementation. Underneath the MainActivity class, add the following:

actual class KMPDate actual constructor(formatString: String) { // 1

    private val dateFormat = SimpleDateFormat(formatString) // 2

    actual fun asString(): String {
        return dateFormat.format(Date()) // 3
    }
}
 

1: The expect declaration of KMPDate stated that it takes a formatString, so an actual constructor implementation accompanies the actual classimplementation.

2: Create a SimpleDateFormat object using the formatString. iOS has an NSDateFormatter class, which is similar to SimpleDateFormat, but we’ll get to later. There is currently no common Kotlin implementation, but for most things, Android and iOS have equivalent features available.

3: The SimpleDateFormat object formats Date() — which produces a Dateobject representing today’s date — into a string.

 

Next, go to

app/src/iosMain/kotlin/sample/SampleIos.kt, which is currently empty. Paste in the following:

 

actual class KMPDate actual constructor(formatString: String) { // 1

    private val dateFormatter = NSDateFormatter().apply { // 2
        this.dateFormat = formatString
    }

    actual fun asString(): String {
        return formatter.stringFromDate(NSDate()) // 3 
    }
}

 

1: Identical to the actual class declaration on the Android side.

2: Pass formatString into an iOSNSDateFormatter object, which — as mentioned earlier — achieves the same result as SimpleDateFormat on Android.

3: The NSDateFormatter object formats a string based on NSDate() — which produces an NSDate object representing today.

 

 

Finally, go back to

/app/src/commonMain/kotlin/sample/Sample.kt. Inside of the Greeting class, create a KMPDate object that takes “MMM dd” as its date format:

private val date = KMPDate("MMM dd")

And last but not least, use string interpolation to insert the formatted date string from each platform into the value of hello():

fun hello(): String =  "Hello, Android and iOS worlds, today is ${date.asString()}!"

 

All done! Run you Android and iOS apps and see the dates displayed on each platform!

As you can see, it’s all about starting small with Kotlin Multiplatform. We recently launched The Touchlab Refactory; an incremental refactoring service with KMP which focuses on a single feature at a time with no disruption to your current development workflow. Learn more here.

We’re hiring!

 
Two Apps in Less than Five Minutes with Kotlin Multiplatform

Two Apps in Less than Five Minutes with Kotlin Multiplatform

If you’re reading this you’ve probably heard a lot about Kotlin Multiplatform, but aren’t sure where to start.

The platform is evolving fast, which means a lot of the docs are out of date, and most of the tutorials seem to walk you through setting up projects and tools from scratch. But nobody likes reading the directions! We’re going to walk you through setting up some shared code in less than five minutes.

Prerequisite: We’ll cheat and not start the clock until you have Xcode 10.3+ and Android Studio 3.4.2 installed, and have an emulator installed and running for Android.

For Xcode, find it on the Mac App Store here and install it. Not on a Mac? Well, none of this will work (you need a Mac).

For Android Studio, go here to get the app, follow instructions here to set it up, and the instructions to setup an Android emulator here. Ready? OK, now start the clock.

Let’s get started.

Clone this repository and open it in Android Studio. The project currently contains two separate Hello World applications: one for Android and iOS each. Run the Android app to see it display “Hello, Android world!”

Now, open /iosApp/iosApp.xcworkspace and run iosApp in the iOS simulator to see it display “Hello, iOS world!” Although they share a folder structure, these iOS and Android apps are separate from one another. Now we’ll join them together with Kotlin Multiplatform.

First, open /app/src/commonMain/kotlin/sample/Sample.kt, which contains the following common code:

package sample

class Greeting {
    fun hello(): String =  "Hello, Android and iOS worlds!"
} 

Next, open /app/src/main/java/sample/SampleAndroid.kt in Android Studio. It contains the Android version of the Hello World app. To make it into a KMP app, replace the value being assigned to textView.text — which is currently “Hello, Android world!” — and replace it with Greeting().hello().

Finally, go back to Xcode and open ViewController.swift. Underneath import UIKit, add import app, which is the name of the KMP library. Then, just like in the Android app, change the value being assigned to label.textfrom “Hello, iOS world!” to Greeting().hello(). Rerun both applications, and see them both displaying the same string!

“Hello, Android and iOS worlds!”

All done! Stop the clock! You’re a Kotlin Multiplatform developer now!

What are some good next steps? Try calling out to some native code with expect/actual statements, then add an existing multiplatform library like Ktor and do some networking.

As you can see, it’s all about starting small with Kotlin Multiplatform. We recently launched The Touchlab Refactory; an incremental refactoring service with KMP which focuses on a single feature at a time with no disruption to your current development workflow. Learn more here.