SlideShare uma empresa Scribd logo
1 de 48
Baixar para ler offline
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

Mais conteúdo relacionado

Mais procurados

Introduction to Kotlin coroutines
Introduction to Kotlin coroutinesIntroduction to Kotlin coroutines
Introduction to Kotlin coroutinesRoman Elizarov
 
[Webinar] Qt Test-Driven Development Using Google Test and Google Mock
[Webinar] Qt Test-Driven Development Using Google Test and Google Mock[Webinar] Qt Test-Driven Development Using Google Test and Google Mock
[Webinar] Qt Test-Driven Development Using Google Test and Google MockICS
 
Whitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsWhitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsYura Nosenko
 
Kotlin Basics & Introduction to Jetpack Compose.pptx
Kotlin Basics & Introduction to Jetpack Compose.pptxKotlin Basics & Introduction to Jetpack Compose.pptx
Kotlin Basics & Introduction to Jetpack Compose.pptxtakshilkunadia
 
What is Kotlin Multiplaform? Why & How?
What is Kotlin Multiplaform? Why & How? What is Kotlin Multiplaform? Why & How?
What is Kotlin Multiplaform? Why & How? Shady Selim
 
Java Multithreading Using Executors Framework
Java Multithreading Using Executors FrameworkJava Multithreading Using Executors Framework
Java Multithreading Using Executors FrameworkArun Mehra
 
Asynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & PromisesAsynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & PromisesHùng Nguyễn Huy
 
Introduction to kotlin coroutines
Introduction to kotlin coroutinesIntroduction to kotlin coroutines
Introduction to kotlin coroutinesNAVER Engineering
 
Utilizing kotlin flows in an android application
Utilizing kotlin flows in an android applicationUtilizing kotlin flows in an android application
Utilizing kotlin flows in an android applicationSeven Peaks Speaks
 
Kotlin vs Java | Edureka
Kotlin vs Java | EdurekaKotlin vs Java | Edureka
Kotlin vs Java | EdurekaEdureka!
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry Sheiko
 
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用Shengyou Fan
 

Mais procurados (20)

Introduction to Kotlin coroutines
Introduction to Kotlin coroutinesIntroduction to Kotlin coroutines
Introduction to Kotlin coroutines
 
[Webinar] Qt Test-Driven Development Using Google Test and Google Mock
[Webinar] Qt Test-Driven Development Using Google Test and Google Mock[Webinar] Qt Test-Driven Development Using Google Test and Google Mock
[Webinar] Qt Test-Driven Development Using Google Test and Google Mock
 
Whitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsWhitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applications
 
Kotlin Basics & Introduction to Jetpack Compose.pptx
Kotlin Basics & Introduction to Jetpack Compose.pptxKotlin Basics & Introduction to Jetpack Compose.pptx
Kotlin Basics & Introduction to Jetpack Compose.pptx
 
What is Kotlin Multiplaform? Why & How?
What is Kotlin Multiplaform? Why & How? What is Kotlin Multiplaform? Why & How?
What is Kotlin Multiplaform? Why & How?
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Java Multithreading Using Executors Framework
Java Multithreading Using Executors FrameworkJava Multithreading Using Executors Framework
Java Multithreading Using Executors Framework
 
Callback Function
Callback FunctionCallback Function
Callback Function
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Asynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & PromisesAsynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & Promises
 
Introduction to kotlin coroutines
Introduction to kotlin coroutinesIntroduction to kotlin coroutines
Introduction to kotlin coroutines
 
Utilizing kotlin flows in an android application
Utilizing kotlin flows in an android applicationUtilizing kotlin flows in an android application
Utilizing kotlin flows in an android application
 
Kotlin vs Java | Edureka
Kotlin vs Java | EdurekaKotlin vs Java | Edureka
Kotlin vs Java | Edureka
 
Introduction to Spring Boot
Introduction to Spring BootIntroduction to Spring Boot
Introduction to Spring Boot
 
Kotlin
KotlinKotlin
Kotlin
 
UI Programming with Qt-Quick and QML
UI Programming with Qt-Quick and QMLUI Programming with Qt-Quick and QML
UI Programming with Qt-Quick and QML
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
 
Clean code slide
Clean code slideClean code slide
Clean code slide
 

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

Kotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyKotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyMobileAcademy
 
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-CNissan Tsafrir
 
Promises - Asynchronous Control Flow
Promises - Asynchronous Control FlowPromises - Asynchronous Control Flow
Promises - Asynchronous Control FlowHenrique 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 Symfony2Aldo Chiecchia
 
Architectures in the compose world
Architectures in the compose worldArchitectures in the compose world
Architectures in the compose worldFabio 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 examplesAlan Arentsen
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyDavid Padbury
 
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 멀티플랫폼 만들기.pdfssuserb6c2641
 
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 developersBartosz Kosarzycki
 
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
 
The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)Domenic Denicola
 

Semelhante a 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 developersKotlin 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 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
 

Mais de 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.pdfCommit 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.pdfCommit 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
 
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à.pptxCommit 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 PACommit 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 forCommit 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 UniversityCommit 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.pdfCommit 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 FunctionsCommit 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 migrazioneCommit University
 
Orchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lcOrchestrare Micro-frontend con micro-lc
Orchestrare Micro-frontend con micro-lcCommit University
 
Fastify has defeated Lagacy-Code
Fastify has defeated Lagacy-CodeFastify has defeated Lagacy-Code
Fastify has defeated Lagacy-CodeCommit University
 
Alpine.js: the outsider Javascript framework
Alpine.js: the outsider Javascript frameworkAlpine.js: the outsider Javascript framework
Alpine.js: the outsider Javascript frameworkCommit University
 

Mais de Commit University (20)

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
 
Alpine.js: the outsider Javascript framework
Alpine.js: the outsider Javascript frameworkAlpine.js: the outsider Javascript framework
Alpine.js: the outsider Javascript framework
 

Último

SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 

Último (20)

SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 

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