One of the most important factors in a successful shared-code implementation is the quality of the API presented. Specifically, what is the experience of a developer calling Kotlin from Swift? Swift interop with Kotlin is amazing, but only relative to other options. The loss of expressive features is a main complaint of iOS developers who are presented with KMP, and this is not simply an aesthetic complaint.
SKIE bridges some important Kotlin features to Swift, in a form that is natural and functional to Swift. That makes writing the API easier for Kotlin devs, and using the API a better experience for Swift devs.
Last year we released KMMBridge to make publishing an iOS Framework easier for KMP teams. We have a Kick Start template repo that is a very basic example of how to publish an SDK. In this post, we’re going to add some new features to that template project, using SKIE to produce a better end result.
Clone the GitHub repo with the updated KMMBridge Kick Start. We will eventually merge this with the main Kick Start sample, but for now grab the following example:
Open that repo in Intellij or Android Studio.
The sample publishes 2 modules. One for analytics, and one for dog breed data. This code is basically a trimmed down version of KaMPKit. We grab and cache dog breed info the Dog CEO API. The user can mark dog breeds as favorites.
Both of these modules are published independently for Android consumers, and an umbrella module is created for iOS consumers. That umbrella module is published as an Xcode Framework.
The original SDK is very basic. The
BreedRepository provided a
Flow with a
List<Breed> objects as it’s subject. This flow is updated as the local database is updated. The repo also has some functions to let you refresh data and update favorite values.
For an Android consumer, the exposed API includes Corotines-aware structures. That is natural for a Kotlin consumer. On the iOS side, we need to adapt those endpoints because, while they will “compile”, trying to call them directly can be problematic.
In the original version, we did this by creating a delegate repositry