TL;DR: Considering KMM as a middle layer to consol...
# multiplatform
a
TL;DR: Considering KMM as a middle layer to consolidate business logic of a large SaaS app. Looking for some advice and guidance about Kotlin - Swift interop. Hi team, Our company has been investing some time & effort into running a PoC for integrating KMM into our existing app. One thing that we noticed was some limitations, or better yet, ground rules to be set in place among the engineers before going ahead with the development of some shared business logic. Just for extra context: our understanding is that we can leverage KMM to write business logic once (something that is currently represented by Interactors + View Models on iOS and Repositories + View Models on Android) and then emit an updated view state to the native layers (Jetpack Compose & SwiftUI) to do the rendering. With that context, one discovery was that the use of
sealed class
in Kotlin is probably better to be limited to the Android specific code only as we can't really get any benefit from it on iOS. While Swift has parametrised enums, the glue layer between KMM and Swift code is Objective C which has no clue of what a sealed class or an enum case with parameters is. One possible workaround we identified was to use
open class
with corresponding subclasses in Kotlin that allows similar pattern matching on both platforms, yet implies certain risks when used at scale. My question is rather complex, but let me put it this way: • Are we on the right track or should we reconsider our approach to sharing code in any way? • What are some other known limitations that we should keep in mind when sharing logic (better yet data structures and method signatures) across different platforms? • Do we need to worry about Swift Strict Concurrency in any way? (Haven't yet tested the solution against some of our Swift 6 packages) Appreciate any insights and help! Thank you
t
On iOS For KMP there's a lack of proper tootling support (on xcode) You need to create custom plugins for example to manage building your project, packaging a fat framework that xcode can use and call via swift. It's a problem as well when switching between device architecture (simulator & iphones). Overall I'd say KMP is still early stages. For anyone looking to migrate from native, I'd say it's still going to be allot of work for you (too much custom infrastructure would need to be built). It needs to be painless, like flutter or React Native. So, I'm working on a new SDK which will help to bridge between swift & kotlin. I'm using this for commercial projects + my own. It has a compile time iOC (that's working well now, just missing incremental building via gradle). It will have a navigation api (to manage routes), cli that write your own scripts, and ability to create your own swift implementations you can use to extend the sdk (on your own dev environment) https://github.com/Ares-Defence-Labs/Atlas
🙏 1
j
@Alex Apriamashvili Check out SKIE, they make some enhancements for the KMP ObjC framework to Swift you could leverage, specifically sealed classes in Kotlin are bridged to enums w/ associated values in Swift side using the
switch onEnum(of:) { }.
I think your on the right track for sharing code, I fully committed to using KMP for sharing all the code in our apps minus obviously the SwiftUI/Compose rendering layer. This includes shared ViewModels, its really nice if you can write all your new code in KMP, very little issues if any so far. Mixing KMP w/ your existing code is going to be the pain point, at least for me it was. But like I said once your stack is fully KMP its real nice and a breeze. Leveraging a good Dependency Injection system is going to be key, because in order to gain access to your platform specific code thru interfaces, conforming existing services/code to this shared KMP interface and injecting these instances from each platform is much easier than having to re-write this code in the KMP layer, or dealing w/ the expect/actual dance.
a
Thank you very much, @Jason! That's so insightful and reassuring! I've just later realised that SKIE wasn't only for translating Flows into AsyncStreams but a bunch of other quality of life things as well, including the sealed classes translation. That's been a really helpful addition to the project. As for the bottom layer integration (i.e services / repos). We're headed in the same direction I believe: declaring an interface in shared source set and implementing it on each platform. Wrt dependency management. Is there anything you could recommend? Thanks again!
j
@Alex Apriamashvili your welcome! I am using Koin for DI, it's fairly easy to use and allows you to use their custom DSL to build modules or they provide Koin attributes so you can attribute classes to build modules up, this is similar to Dagger. I prefer the DSL approach, only downside to Koin is there is no compile time graph validation, so if you happen to forget to register an instance in the Dependency graph, you will find this out during runtime only. Other than that, you just have to expose a few utility functions to the iOS layer and then you can use DI in both native platforms, along w/ shared, its pretty slick. If you happen to go this route, I can provide some guidance if you need it.
a
This sounds awesome! Thanks! I thInk I saw that Koin had the KMP support and I know our Android engineers currently use it in the codebase. I was always iffy on the runtime vs compile time dependency graph validation, but if this is the price to pay to share DI between Android and iOS it makes it more appealing to me 😄 Thank you for your offer in providing some guidance. Let me hit you up once we've got to the DI part 🙏
p
I would strongly advise using DI and interfaces to achieve swift -> Kotlin interop. Whilst the cinterop support does exist, my experience is that it is a bit of a contortion art from the swift perspective (and overlaying objc) to make it work, and feels very experimental at times.
t
@Alex Apriamashvili I’m glad others mentioned SKIE and you think it’ll work for you. SKIE and other touchlab open source tools like xcode-kotlin and kmmbridge have support in #CTJB58X7X if you run into challenges. Koin is also very good and the creators of Koin also watch #C67HDJZ2N
🙌 1
I don’t agree with thearchitect123 that KMP is still early stages. It has gone through experimental-->alpha-->beta-->stable over the past 8 years and has been in production by companies like Careem and Cash App since 2018, and many many more as it continued to mature JetBrains’s strategy has been focused on community-driven development (outside of the core capabilities) which is why they teamed up with Google in 2018 to start the Kotlin Foundation. JetBrains, Google, Touchlab, Gradle, Kotzilla (makers of Koin) and others not on the Foundation but supported by the Foundation like Coil, Multiplatform Settings, KMP-NativeCoroutines have been working hard so that KMP is a mature ecosystem. When the current memory model became default in 2022, we can safely say it was no longer early days.
k
Agree (with @touchlab_justin), KMP has been stable for a while.
On iOS For KMP there's a lack of proper tootling support (on xcode)
You need to create custom plugins for example to manage building your project, packaging a fat framework that xcode can use and call via swift.
It's a problem as well when switching between device architecture (simulator & iphones).
...It needs to be painless, like flutter or React Native.
Flutter and RN need wild, custom plugins to do anything. There's no "proper" tooling support on xcode for those either, because you can't extend Xcode. Our Xcode Kotlin plugin is pushing the boundaries of what's possible with Xcode, because there's very little you can do. Not that the iOS dev experience is good. I wouldn't say it's because it's early days, though, but that there needs to be much more focus on it, and the disparity will have a significant impact on adoption. The big iOC library sounds like a lot. Like you're trying to rebuild everything singlehandedly. Sort of like https://github.com/Ares-Defence-Labs/KmpEssentials 6 months (ish) ago. I've said enough about that, though.