on Android for 1 year • In production on iOS for 7 months • In cities with both apps, ~30% are on iOS • 5 developers on iOS team and 11 on Android Kotlin Multiplatform
Began as a migration of Kotlin to Swift • Difficult to keep up with Android / Kotlin code changes • Inadvertently implemented bugs • Assumptions that weren’t obvious • Tedious
a new repository • Library repository primarily contains common code • Worked with iOS devs to set up and test iOS build • Continued migrating code into this library • Teams began working on UI in parallel behind an interface
• updates would go to the local copy first • sometimes it would take time to merge to the library • frustrating experience for iOS devs using the library
SDK layer • Library usage restricted to a handful of classes • Classes expose alternative interfaces to rest of the code • Consider whether or not sharing architectures makes sense
iOS devs wanted calls with results instead • iOS devs wrote a layer on the iOS side • be intentional about the impact of design decisions on the platforms
have one framework • Building a single framework from a repository is straight forward • Using submodules to make frameworks from multiple repositories is tedious and error prone.
the monolithic module. • Classes are namespaced with baseName in Objective-C. • If it’s not there, it uses the monolith module’s name. • In Swift, classes are not namespaced.
names changed • in Objective-C (ex BaseCore and BaseCore_). • in Swift (ex Core and Core_). • Export is non-transitive by default. Set transitiveExport to make it transitive.
let length = node.value.length print(length) let currentCarNode = CarNode.init().getCarNode() let currentCar = currentCarNode.value print(currentCar.model) }
Touchlab Xcode plugin helps (xcode-kotlin) • Symbolication only in debug builds • experimentally available for release builds in 1.3.60 • Touchlab’s CrashKiOS
-> Void) { let endpoint = BookingRequest(bookingId: bookingId) // called on the Kotlin thread service.request(endpoint) { result in let error: KotlinError? if case .failure(let requestError) = result { error = KotlinError(message: requestError.localizedDescription) } else { error = nil } callback(error) } } }
-> Void) { let endpoint = BookingRequest(bookingId: bookingId) // called on the Kotlin thread service.request(endpoint) { result in let error: KotlinError? if case .failure(let requestError) = result { error = KotlinError(message: requestError.localizedDescription) } else { error = nil } callback(error) } } }
JVM only • mockk doesn’t support multiplatform yet • What more can we share besides business logic? • How do we avoid inheriting technical debt? • Potential impact of sharing common tools • Multithreaded coroutines
multiplatform made it true, and it can work for you too! We share on Android and iOS, our code is clean and not a mess, business logic is what we share, while showing our iOS devs that we care. Most of our code lives in commonMain, to keep our dependencies nice and sane, dependencies implemented on the platform side, we use Dagger on Android with nothing to hide, on Swift we roll our own DI, I speak the truth and do not lie. We build libraries and version them too, updating a changelog with whatever is new, push them to a maven repo to use, and add a tag with nothing to lose. klibs are uploaded for iOS, jars on Android without a mess, the clients use them as you'd expect, and best of all, bugs that we detect - can be fixed on both platforms with ease, saving us half the development fees. With multiplatform coroutines coming soon, the limits are really beyond the moon, so if you haven't considered sharing code, it's a good time to get into this thought mode, that is all i have to say, i hope you enjoyed this talk today.