u/Organic-Anxiety-5166

Driviko - My KMP project and experiences

Hey all,

I released Driviko a few weeks ago — a mileage and expense tracker with OBD support — on both the App Store and Google Play.

I wanted to share some of my experience, and also ask for some real-world testing, especially if you use an OBD module with your car. So please don't hesitate to share any thoughts or feedback.

I'm a professional Android developer with ~15 years of experience. I tried a couple of small personal projects on iOS years ago, but that was before ARC and Swift, so my iOS development experience was very limited.

Because of that, most of the gotchas and details below are iOS-focused — mainly because I'm already used to whatever weirdness exists in the Android world.

App targets

Main stack

  • Core: KMP + CMP, MVVM + Clean Architecture
  • Navigation: custom
  • Resources: custom, Kostra (https://github.com/jbruchanov/kostra)
  • Networking: Ktor + Kotlinx Serialization
  • DI: Koin
  • Charts: custom
  • Storage: SQLDelight
  • Maps: Google Maps (Android + iOS), MapKit on iOS, ArcGIS on JVM
  • Analytics: Firebase
  • Crashlytics: Firebase, BugSnag
  • Testing: Junit5+MockK, plus a tiny custom iOS framework to simulate some MockK-like behaviour

In case you're wondering why navigation/resources are not using Compose/KMP solutions — I started the project before there was anything stable or mature enough to use.

Even now, while the official solutions are probably more powerful compared to my own implementations, I still use mine because I have full control over everything and they work well for my use case.

I might migrate in the future, but that's not a priority right now.

Gotchas, lessons learned, and other details

JVM

  • It's mainly a proof of concept for quick UI testing and general debugging.
  • Desktop JVM generally doesn't provide any usable BT stack for Windows/macOS.
  • Any extra/custom gestures need extra care because of mouse/wheel/keyboard differences.

iOS

  • I trapped myself a few times in Kotlin code with incorrect memory management on iOS. Sometimes it's not easy to see the boundary between iOS ARC and Kotlin GC.
  • Working with collections on iOS can be significantly slower compared to JVM/Android. Using fast* collection operators that avoid iterators was basically a must for my stats calculations. Roughly a 10x improvement.
  • Keyboard handling on iOS is, imo, just painful. For example, numeric keyboards don't provide any "Done/Hide" button, so it has to be implemented manually.
  • The Apple dev stack is just a massive pain coming from the Android world. I can't count how many hours I wasted because of Xcode update -> macOS update -> broken local or CI build. Almost every major update breaks something.
  • Unit testing. Most of my tests are regular JVM unit tests mainly because MockK is unbelievably powerful. A few tests are in commonTest covering both platforms. Given how painful iOS debugging is, I tried to cover as much iOS-specific Kotlin code as possible, so I created a very simplistic fake request/response proxy framework to simulate some MockK-like behaviour on iOS. In general, any code depending on iOS APIs is far from easy to test because of static methods and similar platform specifics.
  • Debugging: This is probably the biggest issue in KMP right now for me. Runtime debugging on iOS is basically unusable because of how slow it is. Most custom eval code in LLDB simply doesn't work, so I ended up relying mostly on logs, which is an extremely frustrating time waster.
  • Build times: My CI runner is a 2018 Mac Mini. Android builds usually finish in under 5 minutes, while iOS is often 30+ minutes. Release builds are around 8 minutes on Android and almost 50 minutes on iOS. A better Mac would probably help, but people complain about iOS build speeds in general, so I doubt it would ever get close to Android build times.
  • I hit a stupid iOS bug that caused an infinite loop. Surprisingly, with the debugger attached, force-killing (swiping away) the app somehow completely broke the LLDB bridge, and after that the app just froze forever on startup. The only fix was rebooting the iPhone.
  • Compose gradients on iOS currently don't support dithering, so if you use gradients with subtle color differences, you need to drop down to the Skiko level and implement a custom solution to avoid visible color banding.
  • Firebase Crashlytics could add official support for KMP. Currently, to see nice KMP stacktraces in iOS Crashlytics, manual workaround is needed. BugSnag works just fine. (Shame on you Google!)

Other

  • As a paying IntelliJ IDEA customer, I'm disappointed. It might be better now, but KMP support used to be heavily blocked by AGP incompatibilities with the built-in Android plugin. Also, running Android Studio and IntelliJ IDEA at the same time confused ADB and prevented debugger attachment from either IDE.
  • I'm using GitHub Actions as CI with a self-hosted macOS runner. The whole iOS build process feels disconnected from Gradle. It's basically a mix of Gradle -> xcodebuild -> Gradle. Setting up a proper end-to-end CI release pipeline required a lot of manual work.
  • My main development workstation is running Windows, which generally works fine, but has some annoying gotchas. iOS targets are defined in Gradle, they're completely ignored on Windows, and the IDE happily autocompletes JVM/Android-only APIs inside shared code that later fail on iOS builds. Because of that, running CI for every code change is basically a must. It would be nice if autocomplete behaved contextually based on the target platform of the edited source set.
  • Screen previews are still limited compared to regular Android apps. AGP9 probably improves this somewhat, but I'm not there yet.
  • iOS strangely doesn't seem to have any clean general isPermissionGranted style API. In some cases, simply creating a related object immediately triggers the permission request flow. That makes it difficult to implement soft-ask UX patterns where a permission is only an optional/nice-to-have feature.

The iOS side of KMP still has a lot of room for improvement.

Most of the friction I experienced was around the build/tooling ecosystem, probably because I'm far less experienced with the iOS toolchain. So much of it still revolves around shell scripts and opaque tooling that it often feels stuck in the past.

AI helps much more nowadays, but with things changing rapidly, it's also common to get outdated or completely wrong answers.

The tight coupling between iOS, Xcode, and macOS versions is another constant source of pain. Several times a year it feels like I'm forced into a major update cycle where something inevitably breaks.

Still, after all the work, I'm really happy with the final result.

The app performs well, and I rarely see any UX/performance issues where Compose/KMP could realistically be blamed.

The release/review process was actually smoother on Apple's side compared to Google.

(Though I definitely miss the old days when creating a project and filling all the required forms didn't take an entire day...)

Is it production ready?

I believe so — but be prepared for some hiccups and friction, especially on the iOS side.

And a little bit of boring stats at the end — roughly measured source code by lines just to see how much is stuff is shared/native.

Prod target       %
-------------------
androidMain    5.1%
commonMain    83.2%
iosMain        6.7%
jvmMain        3.4%
jvmShared      0.9%
mobileMain     0.0%
skikoMain      0.3%
swift          0.4%

Tests

Test target          %
----------------------
androidUnitTest   5.9%
commonTest       16.0%
iosTest           7.0%
jvmTest          71.1%
u/Organic-Anxiety-5166 — 15 hours ago

Debugging iOS KMP

Hi fellow devs,

I'm wondering, how do you debug KMP code on iOS ?
I find it extremely painful.
Currently I'm using android studio,
but just regular debug workflow is mentally slow,
any basic variables preview in "eval window/terminal" doesn't work.

So it's sort of try&log approach which feels like going 50years back...

Am I missing something here ?
I've tried xcode but that has own limits as well, and xcode on its own is just painful to use comparing to android studio.

reddit.com
u/Organic-Anxiety-5166 — 9 days ago