Exposing the separate resources module to iOS target using moko-resources in KMM
In Android development, modularization of the application is a very common pattern that helps organize the code, increase the readability and make sharing between projects more straightforward. Some say it also decreases the build time, but this is not a part of this article. If you would like to learn more, check out this video from Google I/O’19.
Why make a separate module for resources?
Whenever your modules are features or layers based, the resources like localized texts or icons can be used anywhere in the app UI and reused in many modules. Now when compose is becoming a standard we can create UI-only modules with compose dependencies and app resources. The composables do not need to know about any business class.
In the KMM project, the additional benefit can be seen while importing the module. Having the resources independently, the iOS view class will import only this. Same on the Android side, the common module for a ui-only module will not be needed.
Multiplatform resources
For my KMM projects, I use moko-resources. The library from icerock devs provides access to resources on different platforms with the support of the default system localization.
Let’s implement it step by step:
- create a separate module for resources:

- build.gradle needs to include the icerock plugin
dev.icerock.mobile.multiplatform-resources
and an extension functionmultiplatformResources
that will generate the resources classes. Also, we need to addapi
keyword to the library dependency (A gist with a full example)
plugins {
kotlin("multiplatform")
id("com.android.library") id("dev.icerock.mobile.multiplatform-resources")
}
- After adding the resources to
commonMain/resources/MR/base
we should be ready to go to use them everywhere. Disclaimer: Pay attention to the resources directory name. Even if we choose the custom name, the directory needs to be namedMR
- At this point, Android works after importing the new resources module, but iOS does not see it in the generated framework. Why?
Exposing the shared resources to the iOS framework
The iOS target depends on KMM import which in my case is shared
. I didn’t want to add an extra framework for iOS colleagues, so I needed to expose the resources to the common module. In order to do that we need to modify build.gradle
of the shared module.
- include the icerock plugin
dev.icerock.mobile.multiplatform-resources
and an extension functionmultiplatformResources
that will generate the resource classes. Also, we need to addapi
library dependency.
Sounds familiar? This is exactly the same step that we did for the shared resources module before. Check this gist to identify changes in kotlin { } block.
The framework that will be generated for the iOS target needs sharedResources
to be exported together with moko-resources dependency. The first one will contain generated classes while the other is allowing the iOS to use a specific library API. Together with the plugin installed and extension function in the common
module, this project will build iOS, without any change from iOS devs required.
I believe Kotlin Multiplatform is the framework that will be widely used in the mobile world. The reason is, that the KMM is optional and every team can start testing it and implement only a part of it. The resources are a perfect example of how KMM can reduce the amount of duplicated code on mobile platforms.
Big thanks to Carlos Mota for the review 👍