SlideShare a Scribd company logo
KMM Survival Guide:
how to tackle everyday
struggles between Kotlin
and Swift
Emanuele Papa
Commit University November 2022
Working at Zest One in Chiasso, Switzerland
Who I am?
Emanuele Papa, Android Developer
Find me at www.emanuelepapa.dev
What is KMM?
Kotlin Multiplatform
Mobile is an SDK for iOS
and Android app
development. It offers all
the combined benefits of
creating cross-platform
and native apps.
Shared module: you write Kotlin code as you are used to do.
Android module: you see no difference and just use the shared module
code
iOS project: using Kotlin Native, the code is compiled into an
AppleFramework like it was written in Objective-C.
Then you can just use it in the same way as when you import an iOS
dependency.
How does it work?
Swift and Kotlin are both modern languages and have a lot of
syntax similarities
Swift is like Kotlin
Everything looks cool!
I can become an iOS developer!
(or I can become an Android developer!)
Expectation
Not everything on KMM works out of the box.
Unfortunately, most of the issues arise because the
Kotlin code is transformed into ObjectiveC code.
Reality
KMM directly supports Swift interoperability
(KT-49521)
Write shared code in a slightly different way to better
support iOS development (and iOS developers)
Solutions
Primitive types
fun getRandomInt(): Int = Random.nextInt(until = 10)
Shared code
Primitive types
val randomInt: Int = getRandomInt()
Android
Primitive types
let randomInt: Int32 = RandomNumberGeneratorKt.getRandomInt()
iOS
Sealed classes
sealed class KMMIntResult
data class SuccessKMMIntResult(
val value: Int
) : KMMIntResult()
data class ErrorKMMIntResult(
val throwable: Throwable
) : KMMIntResult()
Shared code
Sealed classes
fun getRandomIntWrappedInIntResult(): KMMIntResult {
val isSuccess = Random.nextBoolean()
return if(isSuccess) {
SuccessKMMIntResult(Random.nextInt(until = 10))
} else {
ErrorKMMIntResult(RuntimeException("There was an error, Int not generated"))
}
}
Shared code
Sealed classes
val randomInt: KMMIntResult = getRandomIntWrappedInIntResult()
val randomIntText: String = when (randomInt) {
is KMMIntResult.ErrorKMMIntResult -> {
"Error: ${randomInt.throwable.message}"
}
is KMMIntResult.SuccessKMMIntResult -> {
"Success: ${randomInt.value}"
}
}
Android
Sealed classes
let randomInt: KMMIntResult = RandomNumberGeneratorKt.getRandomIntWrappedInIntResult()
let randomIntText: String
switch randomInt {
case let error as KMMIntResult.ErrorKMMIntResult:
randomIntText = "Error: (error.throwable.message ?? error.throwable.description())"
case let success as KMMIntResult.SuccessKMMIntResult:
randomIntText = "Success: (success.value)"
default:
randomIntText = "This never happens"
}
iOS
Generic sealed class
sealed class KMMResult<out Value>
data class SuccessKMMResult<Value>(
val value: Value
): KMMResult<Value>()
data class ErrorKMMResult(
val throwable: Throwable
): KMMResult<Nothing>()
Shared code
Generic sealed class
fun getRandomIntWrappedInResult(): KMMResult<Int> {
val isSuccess = Random.nextBoolean()
return if(isSuccess) {
SuccessKMMResult(Random.nextInt(until = 10))
} else {
ErrorKMMResult(RuntimeException("There was an error, Int not generated"))
}
}
Shared code
Generic sealed class
Android
val randomInt: KMMResult<Int> = getRandomIntWrappedInResult()
val randomIntText: String = when (randomInt) {
is KMMResult.ErrorKMMResult -> {
"Error: ${randomInt.throwable.message}"
}
is KMMResult.SuccessKMMResult -> {
"Success: ${randomInt.value}"
}
}
Generic sealed class
iOS
let randomInt: KMMResult<KotlinInt> = RandomNumberGeneratorKt.getRandomIntWrappedInIntResult()
let randomIntText: String
switch randomInt {
case let error as KMMResultErrorKMMResult:
randomIntText = "Error: (error.throwable.message ?? error.throwable.description())"
case let success as KMMResultSuccessKMMResult<KotlinInt>:
randomIntText = "Success: (success.value)"
default:
randomIntText = "This never happens"
}
Generics sealed class
First solution
data class ErrorKMMResult(
val throwable: Throwable
): KMMResult<Nothing>()
data class ErrorKMMResult<Value>(
val throwable: Throwable
): KMMResult<Value>()
case let error as
KMMResultErrorKMMResult<KotlinInt>:
case let error as
KMMResultErrorKMMResult:
Generics sealed class
Second solution
enum SwiftResult<Value> {
case error(String)
case success(Value)
}
Generics sealed class
Second solution
func toSwiftResult<Value>(kmmResult: KMMResult<Value>) -> SwiftResult<Value> {
if let successResult = kmmResult as? KMMResultSuccessKMMResult<Value> {
return SwiftResult.success(successResult.value!)
}
if let errorResult = kmmResult as? KMMResultErrorKMMResult {
return SwiftResult.error(errorResult.throwable.message ?? errorResult.throwable.description())
}
return SwiftResult.error("Unexpected error converting to SwiftResult")
}
Use moko-kswift
https://github.com/icerockdev/moko-kswift
KSwift is gradle plugin to generate Swift-friendly API for Kotlin/Native framework.
Note: at the moment, all subclasses in a sealed class must be nested, otherwise the
generation fails.
Generics sealed classes
Definitive solution
public enum KMMResultKs<Value : AnyObject> {
case successKMMResult(KMMResultSuccessKMMResult<Value>)
case errorKMMResult(KMMResultErrorKMMResult<Value>)
public var sealed: KMMResult<Value> {
switch self {
case .successKMMResult(let obj):
return obj as shared.KMMResult<Value>
case .errorKMMResult(let obj):
return obj as shared.KMMResult<Value>
}
}
public init(_ obj: KMMResult<Value>) {
if let obj = obj as? shared.KMMResultSuccessKMMResult<Value> {
self = .successKMMResult(obj)
} else if let obj = obj as? shared.KMMResultErrorKMMResult<Value> {
self = .errorKMMResult(obj)
} else {
fatalError("KMMResultKs not synchronized with KMMResult class")
}
}
}
Generics sealed classes
Inline class
fun formatFirstAndLastName(firstName: String, lastName: String): String =
"$firstName $lastName"
formatFirstAndLastName("Emanuele", "Papa")
formatFirstAndLastName("Papa", "Emanuele")
Shared code
Inline class
fun formatFirstAndLastName(firstName: FirstName, lastName: LastName): String =
"${firstName.firstName} ${lastName.lastName}"
value class FirstName(val firstName: String)
value class LastName(val lastName: String)
formatFirstAndLastName(
FirstName("John"),
LastName("Doe")
)
Shared code
Inline class
ProfileFormatterKt.formatFirstAndLastName(firstName: <Any>, lastName: <Any>)
KT-32352
iOS
Inline class
fun formatFirstAndLastName(
firstName: FirstNameIos,
lastName: LastNameIos
): String {
return formatFirstAndLastName(FirstName(firstName.firstName), LastName(lastName.lastName))
}
data class FirstNameIos(
val firstName: String
)
data class LastNameIos(
val lastName: String
)
Shared iOS code
Inline class
ProfileFormatterKt.formatFirstAndLastName(
firstName: FirstNameIos(firstName: "John"),
lastName: LastNameIos(lastName: "Doe")
)
iOS code
A coroutine is a concurrency design pattern that you
can use on Android to simplify code that executes
asynchronously.
All of this doesn't exist in ObjectiveC
Coroutines
Coroutines
class CoroutinesProfileFormatter {
suspend fun formatFirstAndLastNameWithCoroutines(
firstName: String,
lastName: String
): String {
delay(1000)
return "$firstName $lastName"
}
}
Shared code
Coroutines
fun onShowMyNameClicked() {
viewModelScope.launch {
mutableState.value = mutableState.value.copy(
formattedName = coroutinesProfileFormatter.formatFirstAndLastNameWithCoroutines(
"John",
"Doe"
)
)
}
}
Coroutines
func onShowMyNameClicked() {
coroutinesProfileFormatter.formatFirstAndLastNameWithCoroutines(
firstName: "John",
lastName: "Doe"
) { formattedName, error in
DispatchQueue.main.async {
self.state.formattedName = formattedName!
}
}
}
Coroutines
https://github.com/rickclephas/KMP-NativeCoroutines
Solution
func onShowMyNameWithCombineClicked() {
let formatFirstAndLastNamePublisher = createPublisher(
for: coroutinesProfileFormatter.formatFirstAndLastNameWithCoroutinesNative(
firstName: "Async",
lastName: "Doe"
))
formatFirstAndLastNamePublisher
.subscribe(on: DispatchQueue.main)
.receive(on: DispatchQueue.main)
.sink { completion in
print("Received completion: (completion)")
} receiveValue: { value in
self.state.formattedNameWithAsync = value
}
}
Coroutines
The new memory manager is just being promoted to Beta and it's enabled by
default from Kotlin 1.7.20.
In the new memory manager (MM), we're lifting restrictions on object sharing:
there's no need to freeze objects to share them between threads anymore.
To enable it in Kotlin < 1.7.20
kotlin.native.binary.memoryModel=experimental
https://github.com/JetBrains/kotlin/blob/master/kotlin-native/NEW_MM.md
Result
fun getRandomDouble(): Result<Double> {
return if(Random.nextBoolean()) {
Result.success(Random.nextDouble())
} else {
Result.failure(Throwable("Can't generate a new double"))
}
}
Shared code
Result
fun onShowRandomDoubleClicked() {
val randomDouble = getRandomDouble()
randomDouble.fold(
onSuccess = { double ->
mutableState.value = mutableState.value.copy(formattedRandomDouble = double.toString())
},
onFailure = { throwable ->
mutableState.value = mutableState.value.copy(formattedRandomDouble = throwable.toString())
})
}
Android
Result
func onShowRandomDoubleClicked() {
let randomDouble = RandomDoubleGeneratorKt.getRandomDouble()
//randomDouble has type Any?
state.formattedRandomDouble = String(describing: randomDouble)
}
iOS
This is another thing which code generation might solve...
Default parameters
KT-38685
Exception handling
Kotlin -> Only unchecked exceptions
Swift -> Only checked errors
Exception specified with @Throws -> Propagated as NSError
Exception without @Throws -> iOS crash
Always catch Exceptions in the shared code and return a Result like class
Pure Kotlin -> ✅
KMM library -> ✅
Custom (expect interface, actual 1 native library for Android, 1 native
library for iOS) -> ✅❌
Third-party libraries
class
SystemInfoRetrieverImpl(
private val systemInfoRetriever: SystemInfoRetrieverNativeWrapper
): SystemInfoRetriever
interface
SystemInfoRetrieverNativeWrapper {
fun getSystemName(): String
}
class
SystemInfoRetrieverAndroid :
SystemInfoRetrieverNativeWrapper
class
SystemInfoRetrieverIOS:
SystemInfoRetrieverNativeWrapper
interface
SystemInfoRetriever {
fun getSystemName(): String
}
Third-party libraries
Use this Gradle plugin to create a Swift Package Manager manifest
and an XCFramework for iOS devs when you create a KMM library
SPM
https://github.com/ge-org/multiplatform-swiftpackage
iOS devs will like:
an Xcode plugin which allows debugging of Kotlin code
running in an iOS application, directly from Xcode.
https://github.com/touchlab/xcode-kotlin
IDEs
Android devs will like:
an IDE similar to IntelliJ IDEA/Android Studio but for
iOS: AppCode!
IDEs
Let's hope most of these issues will be
officially fixed soon...
but in the meanwhile, let's rock with
KMM!
The future
Thank you!
Drop a line to e.papa@zest.one
Get in touch with me
www.emanuelepapa.dev

More Related Content

What's hot

Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlin
NAVER Engineering
 
Introduction to Kotlin coroutines
Introduction to Kotlin coroutinesIntroduction to Kotlin coroutines
Introduction to Kotlin coroutines
Roman Elizarov
 
Data Persistence in Android with Room Library
Data Persistence in Android with Room LibraryData Persistence in Android with Room Library
Data Persistence in Android with Room Library
Reinvently
 
Declarative UIs with Jetpack Compose
Declarative UIs with Jetpack ComposeDeclarative UIs with Jetpack Compose
Declarative UIs with Jetpack Compose
Ramon Ribeiro Rabello
 
Quarkus - a next-generation Kubernetes Native Java framework
Quarkus - a next-generation Kubernetes Native Java frameworkQuarkus - a next-generation Kubernetes Native Java framework
Quarkus - a next-generation Kubernetes Native Java framework
SVDevOps
 
Docker swarm
Docker swarmDocker swarm
Discover Quarkus and GraalVM
Discover Quarkus and GraalVMDiscover Quarkus and GraalVM
Discover Quarkus and GraalVM
Romain Schlick
 
Clean architecture with ddd layering in php
Clean architecture with ddd layering in phpClean architecture with ddd layering in php
Clean architecture with ddd layering in php
Leonardo Proietti
 
Modern JavaScript Frameworks: Angular, React & Vue.js
Modern JavaScript Frameworks: Angular, React & Vue.jsModern JavaScript Frameworks: Angular, React & Vue.js
Modern JavaScript Frameworks: Angular, React & Vue.js
Jonas Bandi
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patterns
José Paumard
 
Drools 6.0 (Red Hat Summit)
Drools 6.0 (Red Hat Summit)Drools 6.0 (Red Hat Summit)
Drools 6.0 (Red Hat Summit)
Mark Proctor
 
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
Matt Raible
 
Gradle Introduction
Gradle IntroductionGradle Introduction
Gradle Introduction
Dmitry Buzdin
 
Kubernetes in Docker
Kubernetes in DockerKubernetes in Docker
Kubernetes in Docker
Docker, Inc.
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
intelliyole
 
Docker 101: An Introduction
Docker 101: An IntroductionDocker 101: An Introduction
Docker 101: An Introduction
POSSCON
 
NestJS
NestJSNestJS
NestJS
Wilson Su
 
Docker Birthday #3 - Intro to Docker Slides
Docker Birthday #3 - Intro to Docker SlidesDocker Birthday #3 - Intro to Docker Slides
Docker Birthday #3 - Intro to Docker Slides
Docker, Inc.
 
Json vs Gson vs Jackson
Json vs Gson vs JacksonJson vs Gson vs Jackson
Json vs Gson vs Jackson
Vinaykumar Hebballi
 
Kotlin Jetpack Tutorial
Kotlin Jetpack TutorialKotlin Jetpack Tutorial
Kotlin Jetpack Tutorial
Simplilearn
 

What's hot (20)

Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlin
 
Introduction to Kotlin coroutines
Introduction to Kotlin coroutinesIntroduction to Kotlin coroutines
Introduction to Kotlin coroutines
 
Data Persistence in Android with Room Library
Data Persistence in Android with Room LibraryData Persistence in Android with Room Library
Data Persistence in Android with Room Library
 
Declarative UIs with Jetpack Compose
Declarative UIs with Jetpack ComposeDeclarative UIs with Jetpack Compose
Declarative UIs with Jetpack Compose
 
Quarkus - a next-generation Kubernetes Native Java framework
Quarkus - a next-generation Kubernetes Native Java frameworkQuarkus - a next-generation Kubernetes Native Java framework
Quarkus - a next-generation Kubernetes Native Java framework
 
Docker swarm
Docker swarmDocker swarm
Docker swarm
 
Discover Quarkus and GraalVM
Discover Quarkus and GraalVMDiscover Quarkus and GraalVM
Discover Quarkus and GraalVM
 
Clean architecture with ddd layering in php
Clean architecture with ddd layering in phpClean architecture with ddd layering in php
Clean architecture with ddd layering in php
 
Modern JavaScript Frameworks: Angular, React & Vue.js
Modern JavaScript Frameworks: Angular, React & Vue.jsModern JavaScript Frameworks: Angular, React & Vue.js
Modern JavaScript Frameworks: Angular, React & Vue.js
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patterns
 
Drools 6.0 (Red Hat Summit)
Drools 6.0 (Red Hat Summit)Drools 6.0 (Red Hat Summit)
Drools 6.0 (Red Hat Summit)
 
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
 
Gradle Introduction
Gradle IntroductionGradle Introduction
Gradle Introduction
 
Kubernetes in Docker
Kubernetes in DockerKubernetes in Docker
Kubernetes in Docker
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
 
Docker 101: An Introduction
Docker 101: An IntroductionDocker 101: An Introduction
Docker 101: An Introduction
 
NestJS
NestJSNestJS
NestJS
 
Docker Birthday #3 - Intro to Docker Slides
Docker Birthday #3 - Intro to Docker SlidesDocker Birthday #3 - Intro to Docker Slides
Docker Birthday #3 - Intro to Docker Slides
 
Json vs Gson vs Jackson
Json vs Gson vs JacksonJson vs Gson vs Jackson
Json vs Gson vs Jackson
 
Kotlin Jetpack Tutorial
Kotlin Jetpack TutorialKotlin Jetpack Tutorial
Kotlin Jetpack Tutorial
 

Similar to KMM survival guide: how to tackle struggles between Kotlin and Swift

Kotlin Coroutines and Rx
Kotlin Coroutines and RxKotlin Coroutines and Rx
Kotlin Coroutines and Rx
Shaul Rosenzwieg
 
Kotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyKotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRready
MobileAcademy
 
Kotlin wonderland
Kotlin wonderlandKotlin wonderland
Kotlin wonderland
Jedsada Tiwongvokul
 
Swift - One step forward from Obj-C
Swift -  One step forward from Obj-CSwift -  One step forward from Obj-C
Swift - One step forward from Obj-C
Nissan Tsafrir
 
Promises - Asynchronous Control Flow
Promises - Asynchronous Control FlowPromises - Asynchronous Control Flow
Promises - Asynchronous Control Flow
Henrique Barcelos
 
Meet Elcodi, the flexible e-commerce components built on Symfony2
Meet Elcodi, the flexible e-commerce components built on Symfony2Meet Elcodi, the flexible e-commerce components built on Symfony2
Meet Elcodi, the flexible e-commerce components built on Symfony2
Aldo Chiecchia
 
Architectures in the compose world
Architectures in the compose worldArchitectures in the compose world
Architectures in the compose world
Fabio Collini
 
Ultimate Node.js countdown: the coolest Application Express examples
Ultimate Node.js countdown: the coolest Application Express examplesUltimate Node.js countdown: the coolest Application Express examples
Ultimate Node.js countdown: the coolest Application Express examples
Alan Arentsen
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
David Padbury
 
From dot net_to_rails
From dot net_to_railsFrom dot net_to_rails
From dot net_to_rails
pythonandchips
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Codemotion
 
Kotlin: forse è la volta buona (Trento)
Kotlin: forse è la volta buona (Trento)Kotlin: forse è la volta buona (Trento)
Kotlin: forse è la volta buona (Trento)
Davide Cerbo
 
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdfCompose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
ssuserb6c2641
 
Kotlin Advanced - language reference for Android developers
Kotlin Advanced - language reference for Android developers Kotlin Advanced - language reference for Android developers
Kotlin Advanced - language reference for Android developers
STX Next
 
Kotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developers
Bartosz Kosarzycki
 
Compose in Theory
Compose in TheoryCompose in Theory
Compose in Theory
Garth Gilmour
 
JS class slides (2016)
JS class slides (2016)JS class slides (2016)
JS class slides (2016)
Yves-Emmanuel Jutard
 
JS Class 2016
JS Class 2016JS Class 2016
JS Class 2016
Yves-Emmanuel Jutard
 
The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)
Domenic Denicola
 
ES2015 workflows
ES2015 workflowsES2015 workflows
ES2015 workflows
Jarrod Overson
 

Similar to KMM survival guide: how to tackle struggles between Kotlin and Swift (20)

Kotlin Coroutines and Rx
Kotlin Coroutines and RxKotlin Coroutines and Rx
Kotlin Coroutines and Rx
 
Kotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyKotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRready
 
Kotlin wonderland
Kotlin wonderlandKotlin wonderland
Kotlin wonderland
 
Swift - One step forward from Obj-C
Swift -  One step forward from Obj-CSwift -  One step forward from Obj-C
Swift - One step forward from Obj-C
 
Promises - Asynchronous Control Flow
Promises - Asynchronous Control FlowPromises - Asynchronous Control Flow
Promises - Asynchronous Control Flow
 
Meet Elcodi, the flexible e-commerce components built on Symfony2
Meet Elcodi, the flexible e-commerce components built on Symfony2Meet Elcodi, the flexible e-commerce components built on Symfony2
Meet Elcodi, the flexible e-commerce components built on Symfony2
 
Architectures in the compose world
Architectures in the compose worldArchitectures in the compose world
Architectures in the compose world
 
Ultimate Node.js countdown: the coolest Application Express examples
Ultimate Node.js countdown: the coolest Application Express examplesUltimate Node.js countdown: the coolest Application Express examples
Ultimate Node.js countdown: the coolest Application Express examples
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
From dot net_to_rails
From dot net_to_railsFrom dot net_to_rails
From dot net_to_rails
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
 
Kotlin: forse è la volta buona (Trento)
Kotlin: forse è la volta buona (Trento)Kotlin: forse è la volta buona (Trento)
Kotlin: forse è la volta buona (Trento)
 
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdfCompose로 Android:Desktop 멀티플랫폼 만들기.pdf
Compose로 Android:Desktop 멀티플랫폼 만들기.pdf
 
Kotlin Advanced - language reference for Android developers
Kotlin Advanced - language reference for Android developers Kotlin Advanced - language reference for Android developers
Kotlin Advanced - language reference for Android developers
 
Kotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developers
 
Compose in Theory
Compose in TheoryCompose in Theory
Compose in Theory
 
JS class slides (2016)
JS class slides (2016)JS class slides (2016)
JS class slides (2016)
 
JS Class 2016
JS Class 2016JS Class 2016
JS Class 2016
 
The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)
 
ES2015 workflows
ES2015 workflowsES2015 workflows
ES2015 workflows
 

More from Commit University

Alla scoperta dei Vector Database e dei RAG
Alla scoperta dei Vector Database e dei RAGAlla scoperta dei Vector Database e dei RAG
Alla scoperta dei Vector Database e dei RAG
Commit University
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
Commit University
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Commit University
 
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdfBreaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Commit University
 
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdfAccelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Commit University
 
Slide-10years.pdf
Slide-10years.pdfSlide-10years.pdf
Slide-10years.pdf
Commit University
 
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Commit University
 
Vue.js slots.pdf
Vue.js slots.pdfVue.js slots.pdf
Vue.js slots.pdf
Commit University
 
Commit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptxCommit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptx
Commit University
 
Sviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PASviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PA
Commit University
 
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Commit University
 
Prisma the ORM that node was waiting for
Prisma the ORM that node was waiting forPrisma the ORM that node was waiting for
Prisma the ORM that node was waiting for
Commit University
 
Decision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit UniversityDecision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit University
Commit University
 
Component Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdfComponent Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdf
Commit University
 
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Commit University
 
Prototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step FunctionsPrototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step Functions
Commit University
 
Da Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneDa Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazione
Commit University
 
Orchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lcOrchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lc
Commit University
 
Fastify has defeated Lagacy-Code
Fastify has defeated Lagacy-CodeFastify has defeated Lagacy-Code
Fastify has defeated Lagacy-Code
Commit University
 
SwiftUI vs UIKit
SwiftUI vs UIKitSwiftUI vs UIKit
SwiftUI vs UIKit
Commit University
 

More from Commit University (20)

Alla scoperta dei Vector Database e dei RAG
Alla scoperta dei Vector Database e dei RAGAlla scoperta dei Vector Database e dei RAG
Alla scoperta dei Vector Database e dei RAG
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdfBreaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
Breaking REST Chains_ A Fastify & Mercurius Pathway to GraphQL Glory.pdf
 
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdfAccelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
Accelerating API Development: A Pit Stop with Gin-Gonic in Golang-Slide.pdf
 
Slide-10years.pdf
Slide-10years.pdfSlide-10years.pdf
Slide-10years.pdf
 
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
Collaborazione, Decisionalità e Gestione della Complessità nel Tempo: cosa ...
 
Vue.js slots.pdf
Vue.js slots.pdfVue.js slots.pdf
Vue.js slots.pdf
 
Commit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptxCommit - Qwik il framework che ti stupirà.pptx
Commit - Qwik il framework che ti stupirà.pptx
 
Sviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PASviluppare da zero una Angular Web App per la PA
Sviluppare da zero una Angular Web App per la PA
 
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
Backstage l'Internal Developer Portal Open Source per una migliore Developer ...
 
Prisma the ORM that node was waiting for
Prisma the ORM that node was waiting forPrisma the ORM that node was waiting for
Prisma the ORM that node was waiting for
 
Decision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit UniversityDecision-making for Software Development Teams - Commit University
Decision-making for Software Development Teams - Commit University
 
Component Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdfComponent Design Pattern nei Game Engine.pdf
Component Design Pattern nei Game Engine.pdf
 
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
Un viaggio alla scoperta dei Language Models e dell’intelligenza artificiale ...
 
Prototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step FunctionsPrototipazione Low-Code con AWS Step Functions
Prototipazione Low-Code con AWS Step Functions
 
Da Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazioneDa Vuex a Pinia: come fare la migrazione
Da Vuex a Pinia: come fare la migrazione
 
Orchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lcOrchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lc
 
Fastify has defeated Lagacy-Code
Fastify has defeated Lagacy-CodeFastify has defeated Lagacy-Code
Fastify has defeated Lagacy-Code
 
SwiftUI vs UIKit
SwiftUI vs UIKitSwiftUI vs UIKit
SwiftUI vs UIKit
 

Recently uploaded

Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Pitangent Analytics & Technology Solutions Pvt. Ltd
 
Demystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through StorytellingDemystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through Storytelling
Enterprise Knowledge
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
Tatiana Kojar
 
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptxPRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
christinelarrosa
 
Apps Break Data
Apps Break DataApps Break Data
Apps Break Data
Ivo Velitchkov
 
GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)
Javier Junquera
 
Session 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdfSession 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdf
UiPathCommunity
 
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin..."$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
Fwdays
 
AppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSFAppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSF
Ajin Abraham
 
High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024
Vadym Kazulkin
 
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
Edge AI and Vision Alliance
 
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
saastr
 
Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving | Nameplate Manufacturing Process - 2024Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
MichaelKnudsen27
 
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-EfficiencyFreshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
ScyllaDB
 
Northern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving | Modern Metal Trim, Nameplates and Appliance PanelsNorthern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
DianaGray10
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
Pablo Gómez Abajo
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
Chart Kalyan
 
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansBiomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Neo4j
 

Recently uploaded (20)

Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
 
Demystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through StorytellingDemystifying Knowledge Management through Storytelling
Demystifying Knowledge Management through Storytelling
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
 
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptxPRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
PRODUCT LISTING OPTIMIZATION PRESENTATION.pptx
 
Apps Break Data
Apps Break DataApps Break Data
Apps Break Data
 
GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)GNSS spoofing via SDR (Criptored Talks 2024)
GNSS spoofing via SDR (Criptored Talks 2024)
 
Session 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdfSession 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdf
 
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin..."$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
 
AppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSFAppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSF
 
High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024
 
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
 
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
 
Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving | Nameplate Manufacturing Process - 2024Northern Engraving | Nameplate Manufacturing Process - 2024
Northern Engraving | Nameplate Manufacturing Process - 2024
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
 
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-EfficiencyFreshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
 
Northern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving | Modern Metal Trim, Nameplates and Appliance PanelsNorthern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
Northern Engraving | Modern Metal Trim, Nameplates and Appliance Panels
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
 
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansBiomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
 

KMM survival guide: how to tackle struggles between Kotlin and Swift

  • 1. KMM Survival Guide: how to tackle everyday struggles between Kotlin and Swift Emanuele Papa Commit University November 2022
  • 2. Working at Zest One in Chiasso, Switzerland Who I am? Emanuele Papa, Android Developer Find me at www.emanuelepapa.dev
  • 3. What is KMM? Kotlin Multiplatform Mobile is an SDK for iOS and Android app development. It offers all the combined benefits of creating cross-platform and native apps.
  • 4. Shared module: you write Kotlin code as you are used to do. Android module: you see no difference and just use the shared module code iOS project: using Kotlin Native, the code is compiled into an AppleFramework like it was written in Objective-C. Then you can just use it in the same way as when you import an iOS dependency. How does it work?
  • 5. Swift and Kotlin are both modern languages and have a lot of syntax similarities Swift is like Kotlin
  • 6. Everything looks cool! I can become an iOS developer! (or I can become an Android developer!) Expectation
  • 7. Not everything on KMM works out of the box. Unfortunately, most of the issues arise because the Kotlin code is transformed into ObjectiveC code. Reality
  • 8. KMM directly supports Swift interoperability (KT-49521) Write shared code in a slightly different way to better support iOS development (and iOS developers) Solutions
  • 9. Primitive types fun getRandomInt(): Int = Random.nextInt(until = 10) Shared code
  • 10. Primitive types val randomInt: Int = getRandomInt() Android
  • 11. Primitive types let randomInt: Int32 = RandomNumberGeneratorKt.getRandomInt() iOS
  • 12. Sealed classes sealed class KMMIntResult data class SuccessKMMIntResult( val value: Int ) : KMMIntResult() data class ErrorKMMIntResult( val throwable: Throwable ) : KMMIntResult() Shared code
  • 13. Sealed classes fun getRandomIntWrappedInIntResult(): KMMIntResult { val isSuccess = Random.nextBoolean() return if(isSuccess) { SuccessKMMIntResult(Random.nextInt(until = 10)) } else { ErrorKMMIntResult(RuntimeException("There was an error, Int not generated")) } } Shared code
  • 14. Sealed classes val randomInt: KMMIntResult = getRandomIntWrappedInIntResult() val randomIntText: String = when (randomInt) { is KMMIntResult.ErrorKMMIntResult -> { "Error: ${randomInt.throwable.message}" } is KMMIntResult.SuccessKMMIntResult -> { "Success: ${randomInt.value}" } } Android
  • 15. Sealed classes let randomInt: KMMIntResult = RandomNumberGeneratorKt.getRandomIntWrappedInIntResult() let randomIntText: String switch randomInt { case let error as KMMIntResult.ErrorKMMIntResult: randomIntText = "Error: (error.throwable.message ?? error.throwable.description())" case let success as KMMIntResult.SuccessKMMIntResult: randomIntText = "Success: (success.value)" default: randomIntText = "This never happens" } iOS
  • 16. Generic sealed class sealed class KMMResult<out Value> data class SuccessKMMResult<Value>( val value: Value ): KMMResult<Value>() data class ErrorKMMResult( val throwable: Throwable ): KMMResult<Nothing>() Shared code
  • 17. Generic sealed class fun getRandomIntWrappedInResult(): KMMResult<Int> { val isSuccess = Random.nextBoolean() return if(isSuccess) { SuccessKMMResult(Random.nextInt(until = 10)) } else { ErrorKMMResult(RuntimeException("There was an error, Int not generated")) } } Shared code
  • 18. Generic sealed class Android val randomInt: KMMResult<Int> = getRandomIntWrappedInResult() val randomIntText: String = when (randomInt) { is KMMResult.ErrorKMMResult -> { "Error: ${randomInt.throwable.message}" } is KMMResult.SuccessKMMResult -> { "Success: ${randomInt.value}" } }
  • 19. Generic sealed class iOS let randomInt: KMMResult<KotlinInt> = RandomNumberGeneratorKt.getRandomIntWrappedInIntResult() let randomIntText: String switch randomInt { case let error as KMMResultErrorKMMResult: randomIntText = "Error: (error.throwable.message ?? error.throwable.description())" case let success as KMMResultSuccessKMMResult<KotlinInt>: randomIntText = "Success: (success.value)" default: randomIntText = "This never happens" }
  • 20. Generics sealed class First solution data class ErrorKMMResult( val throwable: Throwable ): KMMResult<Nothing>() data class ErrorKMMResult<Value>( val throwable: Throwable ): KMMResult<Value>() case let error as KMMResultErrorKMMResult<KotlinInt>: case let error as KMMResultErrorKMMResult:
  • 21. Generics sealed class Second solution enum SwiftResult<Value> { case error(String) case success(Value) }
  • 22. Generics sealed class Second solution func toSwiftResult<Value>(kmmResult: KMMResult<Value>) -> SwiftResult<Value> { if let successResult = kmmResult as? KMMResultSuccessKMMResult<Value> { return SwiftResult.success(successResult.value!) } if let errorResult = kmmResult as? KMMResultErrorKMMResult { return SwiftResult.error(errorResult.throwable.message ?? errorResult.throwable.description()) } return SwiftResult.error("Unexpected error converting to SwiftResult") }
  • 23. Use moko-kswift https://github.com/icerockdev/moko-kswift KSwift is gradle plugin to generate Swift-friendly API for Kotlin/Native framework. Note: at the moment, all subclasses in a sealed class must be nested, otherwise the generation fails. Generics sealed classes Definitive solution
  • 24. public enum KMMResultKs<Value : AnyObject> { case successKMMResult(KMMResultSuccessKMMResult<Value>) case errorKMMResult(KMMResultErrorKMMResult<Value>) public var sealed: KMMResult<Value> { switch self { case .successKMMResult(let obj): return obj as shared.KMMResult<Value> case .errorKMMResult(let obj): return obj as shared.KMMResult<Value> } } public init(_ obj: KMMResult<Value>) { if let obj = obj as? shared.KMMResultSuccessKMMResult<Value> { self = .successKMMResult(obj) } else if let obj = obj as? shared.KMMResultErrorKMMResult<Value> { self = .errorKMMResult(obj) } else { fatalError("KMMResultKs not synchronized with KMMResult class") } } } Generics sealed classes
  • 25. Inline class fun formatFirstAndLastName(firstName: String, lastName: String): String = "$firstName $lastName" formatFirstAndLastName("Emanuele", "Papa") formatFirstAndLastName("Papa", "Emanuele") Shared code
  • 26. Inline class fun formatFirstAndLastName(firstName: FirstName, lastName: LastName): String = "${firstName.firstName} ${lastName.lastName}" value class FirstName(val firstName: String) value class LastName(val lastName: String) formatFirstAndLastName( FirstName("John"), LastName("Doe") ) Shared code
  • 28. Inline class fun formatFirstAndLastName( firstName: FirstNameIos, lastName: LastNameIos ): String { return formatFirstAndLastName(FirstName(firstName.firstName), LastName(lastName.lastName)) } data class FirstNameIos( val firstName: String ) data class LastNameIos( val lastName: String ) Shared iOS code
  • 29. Inline class ProfileFormatterKt.formatFirstAndLastName( firstName: FirstNameIos(firstName: "John"), lastName: LastNameIos(lastName: "Doe") ) iOS code
  • 30. A coroutine is a concurrency design pattern that you can use on Android to simplify code that executes asynchronously. All of this doesn't exist in ObjectiveC Coroutines
  • 31. Coroutines class CoroutinesProfileFormatter { suspend fun formatFirstAndLastNameWithCoroutines( firstName: String, lastName: String ): String { delay(1000) return "$firstName $lastName" } } Shared code
  • 32. Coroutines fun onShowMyNameClicked() { viewModelScope.launch { mutableState.value = mutableState.value.copy( formattedName = coroutinesProfileFormatter.formatFirstAndLastNameWithCoroutines( "John", "Doe" ) ) } }
  • 33. Coroutines func onShowMyNameClicked() { coroutinesProfileFormatter.formatFirstAndLastNameWithCoroutines( firstName: "John", lastName: "Doe" ) { formattedName, error in DispatchQueue.main.async { self.state.formattedName = formattedName! } } }
  • 34. Coroutines https://github.com/rickclephas/KMP-NativeCoroutines Solution func onShowMyNameWithCombineClicked() { let formatFirstAndLastNamePublisher = createPublisher( for: coroutinesProfileFormatter.formatFirstAndLastNameWithCoroutinesNative( firstName: "Async", lastName: "Doe" )) formatFirstAndLastNamePublisher .subscribe(on: DispatchQueue.main) .receive(on: DispatchQueue.main) .sink { completion in print("Received completion: (completion)") } receiveValue: { value in self.state.formattedNameWithAsync = value } }
  • 35. Coroutines The new memory manager is just being promoted to Beta and it's enabled by default from Kotlin 1.7.20. In the new memory manager (MM), we're lifting restrictions on object sharing: there's no need to freeze objects to share them between threads anymore. To enable it in Kotlin < 1.7.20 kotlin.native.binary.memoryModel=experimental https://github.com/JetBrains/kotlin/blob/master/kotlin-native/NEW_MM.md
  • 36. Result fun getRandomDouble(): Result<Double> { return if(Random.nextBoolean()) { Result.success(Random.nextDouble()) } else { Result.failure(Throwable("Can't generate a new double")) } } Shared code
  • 37. Result fun onShowRandomDoubleClicked() { val randomDouble = getRandomDouble() randomDouble.fold( onSuccess = { double -> mutableState.value = mutableState.value.copy(formattedRandomDouble = double.toString()) }, onFailure = { throwable -> mutableState.value = mutableState.value.copy(formattedRandomDouble = throwable.toString()) }) } Android
  • 38. Result func onShowRandomDoubleClicked() { let randomDouble = RandomDoubleGeneratorKt.getRandomDouble() //randomDouble has type Any? state.formattedRandomDouble = String(describing: randomDouble) } iOS
  • 39. This is another thing which code generation might solve... Default parameters KT-38685
  • 40. Exception handling Kotlin -> Only unchecked exceptions Swift -> Only checked errors Exception specified with @Throws -> Propagated as NSError Exception without @Throws -> iOS crash Always catch Exceptions in the shared code and return a Result like class
  • 41. Pure Kotlin -> ✅ KMM library -> ✅ Custom (expect interface, actual 1 native library for Android, 1 native library for iOS) -> ✅❌ Third-party libraries
  • 42. class SystemInfoRetrieverImpl( private val systemInfoRetriever: SystemInfoRetrieverNativeWrapper ): SystemInfoRetriever interface SystemInfoRetrieverNativeWrapper { fun getSystemName(): String } class SystemInfoRetrieverAndroid : SystemInfoRetrieverNativeWrapper class SystemInfoRetrieverIOS: SystemInfoRetrieverNativeWrapper interface SystemInfoRetriever { fun getSystemName(): String } Third-party libraries
  • 43. Use this Gradle plugin to create a Swift Package Manager manifest and an XCFramework for iOS devs when you create a KMM library SPM https://github.com/ge-org/multiplatform-swiftpackage
  • 44. iOS devs will like: an Xcode plugin which allows debugging of Kotlin code running in an iOS application, directly from Xcode. https://github.com/touchlab/xcode-kotlin IDEs
  • 45. Android devs will like: an IDE similar to IntelliJ IDEA/Android Studio but for iOS: AppCode! IDEs
  • 46. Let's hope most of these issues will be officially fixed soon... but in the meanwhile, let's rock with KMM! The future
  • 48. Drop a line to e.papa@zest.one Get in touch with me www.emanuelepapa.dev