{"id":15293501,"url":"https://github.com/icerockdev/moko-kswift","last_synced_at":"2025-04-04T20:14:57.111Z","repository":{"id":37936638,"uuid":"392317237","full_name":"icerockdev/moko-kswift","owner":"icerockdev","description":"Swift-friendly api generator for Kotlin/Native frameworks","archived":false,"fork":false,"pushed_at":"2024-01-22T04:55:43.000Z","size":1572,"stargazers_count":353,"open_issues_count":33,"forks_count":22,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-28T19:11:57.809Z","etag":null,"topics":["gradle-plugin","kotlin-multiplatform","kotlin-multiplatform-mobile","kotlin-native","moko","swift"],"latest_commit_sha":null,"homepage":"https://moko.icerock.dev","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/icerockdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-08-03T12:54:01.000Z","updated_at":"2025-03-21T15:29:25.000Z","dependencies_parsed_at":"2024-12-21T03:09:09.784Z","dependency_job_id":"4837f676-b7f6-47ec-a0f9-6cdeeb82a9c9","html_url":"https://github.com/icerockdev/moko-kswift","commit_stats":{"total_commits":103,"total_committers":8,"mean_commits":12.875,"dds":0.2038834951456311,"last_synced_commit":"cccacec4041b52084c6f1200ce25e99ebc55818d"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icerockdev%2Fmoko-kswift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icerockdev%2Fmoko-kswift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icerockdev%2Fmoko-kswift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icerockdev%2Fmoko-kswift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/icerockdev","download_url":"https://codeload.github.com/icerockdev/moko-kswift/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247242681,"owners_count":20907134,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gradle-plugin","kotlin-multiplatform","kotlin-multiplatform-mobile","kotlin-native","moko","swift"],"created_at":"2024-09-30T16:49:47.292Z","updated_at":"2025-04-04T20:14:57.093Z","avatar_url":"https://github.com/icerockdev.png","language":"Kotlin","readme":"![moko-kswift](https://user-images.githubusercontent.com/5010169/128708262-81403e12-4ddb-4ff6-8d9d-feda2fd95bf3.png)  \n[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0) [![Download](https://img.shields.io/maven-central/v/dev.icerock.moko/kswift-runtime) ](https://repo1.maven.org/maven2/dev/icerock/moko/kswift-runtime) ![kotlin-version](https://kotlin-version.aws.icerock.dev/kotlin-version?group=dev.icerock.moko\u0026name=kswift-runtime)\n\n# MOKO KSwift\n\nKSwift it's gradle plugin for generation Swift-friendly API for Kotlin/Native framework.\n\n## Kotlin sealed interface/class to Swift enum\n\n![sealed classes compare](https://user-images.githubusercontent.com/5010169/128596479-688bce59-b224-402f-8f5b-8b32d33aa0b5.png)\n\n## Kotlin extensions for K/N platform classes\n\n![extensions compare](https://user-images.githubusercontent.com/5010169/128596630-28af4922-fcee-4eae-979b-0bad3722f0d2.png)\n\n## Your own case\n\nKSwift give you API for adding your own generator based on KLib metadata information.\n\n# Posts\n\n- [How to implement Swift-friendly API with Kotlin Multiplatform Mobile](https://medium.com/icerock/how-to-implement-swift-friendly-api-with-kotlin-multiplatform-mobile-e68521a63b6d)\n\n# Table of Contents\n\n- [Features](#features)\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Usage](#usage)\n- [FAQ](#faq)\n- [Samples](#samples)\n- [Set Up Locally](#set-up-locally)\n- [Contributing](#contributing)\n- [License](#license)\n\n# Features\n\n- **API for extend logic for own cases** - just implement your own `ProcessorFeature`\n- **Reading of all exported klibs** - you can generate swift additions to the api of external\n  libraries\n- **Kotlin sealed class/interface to Swift enum**\n- **Kotlin extensions for platform classes to correct extensions** instead of additional class with\n  static methods\n- **Flexible filtration** - select what you want to generate and what not\n\n# Requirements\n\n- Gradle version 6.0+\n- Kotlin 1.6.10\n\n# Installation\n\n## Plugin\n\n### Using legacy plugin application\n\nroot `build.gradle`\n\n```groovy\nbuildscript {\n    repositories {\n        mavenCentral()\n        google()\n        gradlePluginPortal()\n    }\n    dependencies {\n        classpath(\"dev.icerock.moko:kswift-gradle-plugin:0.7.0\")\n    }\n}\n```\n\nproject where framework compiles `build.gradle`\n\n```groovy\nplugins {\n    id(\"dev.icerock.moko.kswift\")\n}\n```\n\n### Using the plugins DSL\n\n`settings.gradle`\n\n```groovy\npluginManagement {\n    repositories {\n        google()\n        gradlePluginPortal()\n        mavenCentral()\n    }\n}\n```\n\nproject where framework compiles `build.gradle`\n\n```groovy\nplugins {\n    id(\"dev.icerock.moko.kswift\") version \"0.7.0\"\n}\n```\n\n## Runtime library\n\nroot `build.gradle`\n\n```groovy\nallprojects {\n    repositories {\n        mavenCentral()\n    }\n}\n```\n\nproject `build.gradle`\n\n```groovy\ndependencies {\n    commonMainApi(\"dev.icerock.moko:kswift-runtime:0.7.0\") // if you want use annotations\n}\n```\n\n# Usage\n\n## Xcode configuration\n\nThe Swift code generated from this plugin is not automatically included in the shared framework you might have.\n\nYou have 2 options to use it in your iOS project:\n- Xcode direct file integration\n- CocoaPods integration\n\n### Xcode direct file integration\n\nYou can directly import the generated file in your Xcode project like it's a file you have written on your own.\n\nTo do so:\n- open the Xcode project\n- right click on \"iosApp\"\n- choose \"Add files to iOSApp\"\n- add the file from the generated folder (you might need to read the FAQ to know where the generated folder is)\n- you are now good to go!\n\n### CocoaPods integration\n\nAfter you have added the moko-kswift plugin to your shared module and synced your project, a new Gradle task should appear with name `kSwiftXXXXXPodspec` where `XXXXX` is the name of your shared module (so your task might be named `kSwiftsharedPodspec`).\n\n- Run the task doing `./gradlew kSwiftsharedPodspec` from the root of your project.\n  This will generate a new podspec file, `XXXXXSwift.podspec`, where `XXXXX` is still the name of your shared module (so e.g. `sharedSwift.podspec`)\n\n- Now edit the `Podfile` inside the iOS project adding this line\n  `pod 'sharedSwift', :path =\u003e '../shared'`\n  just after the one already there for the already available shared module\n  `pod 'shared', :path =\u003e '../shared'`\n\n- Now run `pod install` from the `iosApp` folder so the new framework is linked to your project.\n\n- Whenever you need a Swift file generated from moko-kswift just import the generated module (e.g. `import sharedSwift`) and you are good to go!\n\n## Sealed classes/interfaces to Swift enum\n\nEnable feature in project `build.gradle`:\n\nkotlin:\n```kotlin\nkswift {\n    install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature)\n}\n```\n\ngroovy:\n```groovy\nkswift {\n    install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature.factory)\n}\n```\n\nThat's all - after this setup all sealed classes and sealed interfaces will be parsed by plugin and\nplugin will generate Swift enums for this classes.\n\nFor example if you have in your kotlin code:\n\n```kotlin\nsealed interface UIState\u003cout T\u003e {\n    object Loading : UIState\u003cNothing\u003e\n    object Empty : UIState\u003cNothing\u003e\n    data class Data\u003cT\u003e(val value: T) : UIState\u003cT\u003e\n    data class Error(val throwable: Throwable) : UIState\u003cNothing\u003e\n}\n```\n\nThen plugin will generate source code:\n\n```swift\n/**\n * selector: ClassContext/moko-kswift.sample:mpp-library-pods/com/icerockdev/library/UIState */\npublic enum UIStateKs\u003cT : AnyObject\u003e {\n\n  case loading\n  case empty\n  case data(UIStateData\u003cT\u003e)\n  case error(UIStateError)\n\n  public init(_ obj: UIState) {\n    if obj is shared.UIStateLoading {\n      self = .loading\n    } else if obj is shared.UIStateEmpty {\n      self = .empty\n    } else if let obj = obj as? shared.UIStateData\u003cT\u003e {\n      self = .data(obj)\n    } else if let obj = obj as? shared.UIStateError {\n      self = .error(obj)\n    } else {\n      fatalError(\"UIStateKs not syncronized with UIState class\")\n    }\n  }\n\n}\n```\n\nFor each generated entry in comment generated `selector` - value of this selector can be used for\nfilter. By default all entries generated. But if generated code invalid (please report issue in this\ncase) you can disable generation of this particular entry:\n\nkotlin:\n```kotlin\nkswift {\n    install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature) {\n        filter = excludeFilter(\"ClassContext/moko-kswift.sample:mpp-library-pods/com/icerockdev/library/UIState\")\n    }\n}\n```\n\ngroovy:\n```groovy\nkswift {\n    install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature.factory) {\n        it.filter = it.excludeFilter(\"ClassContext/moko-kswift.sample:mpp-library-pods/com/icerockdev/library/UIState\")\n    }\n}\n```\n\nAs alternative you can use `includeFilter` to explicit setup each required for generation entries:\n\nkotlin:\n```kotlin\nkswift {\n    install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature) {\n        filter = includeFilter(\"ClassContext/moko-kswift.sample:mpp-library-pods/com/icerockdev/library/UIState\")\n    }\n}\n```\n\ngroovy:\n```groovy\nkswift {\n    install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature.factory) {\n        it.filter = it.includeFilter(\"ClassContext/moko-kswift.sample:mpp-library-pods/com/icerockdev/library/UIState\")\n    }\n}\n```\n\n## Extensions from platform classes\n\nEnable feature in project `build.gradle`:\n\nkotlin:\n```kotlin\nkswift {\n    install(dev.icerock.moko.kswift.plugin.feature.PlatformExtensionFunctionsFeature)\n}\n```\n\ngroovy:\n```groovy\nkswift {\n    install(dev.icerock.moko.kswift.plugin.feature.PlatformExtensionFunctionsFeature.factory)\n}\n```\n\nThat's all - after this setup all extension functions for classes from `platform.*` package will be\ncorrect swift code.\n\nFor example if you have in your kotlin code:\n\n```kotlin\nclass CFlow\u003cT\u003e(private val stateFlow: StateFlow\u003cT\u003e) : StateFlow\u003cT\u003e by stateFlow\n\nfun UILabel.bindText(coroutineScope: CoroutineScope, flow: CFlow\u003cString\u003e) {\n    val label = this\n    coroutineScope.launch {\n        label.text = flow.value\n        flow.collect { label.text = it }\n    }\n}\n```\n\nThen plugin will generate source code:\n\n```swift\npublic extension UIKit.UILabel {\n  /**\n   * selector: PackageFunctionContext/moko-kswift.sample:mpp-library/com.icerockdev.library/Class(name=platform/UIKit/UILabel)/bindText/coroutineScope:Class(name=kotlinx/coroutines/CoroutineScope),flow:Class(name=com/icerockdev/library/CFlow)\u003cClass(name=kotlin/String)\u003e */\n  public func bindText(coroutineScope: CoroutineScope, flow: CFlow\u003cNSString\u003e) {\n    return UILabelExtKt.bindText(self, coroutineScope: coroutineScope, flow: flow)\n  }\n}\n```\n\nSelector from comment can be used for filters as in first example.\n\n## Generation of Swift copy method for data classes\n\nEnable feature in project `build.gradle`:\n\nkotlin:\n```kotlin\nkswift {\n    install(dev.icerock.moko.kswift.plugin.feature.DataClassCopyFeature)\n}\n```\n\ngroovy:\n```groovy\nkswift {\n    install(dev.icerock.moko.kswift.plugin.feature.DataClassCopyFeature.factory)\n}\n```\n\nWith this feature for data class like this:\n```kotlin\ndata class DataClass(\n    val stringValue: String,\n    val optionalStringValue: String?,\n    val intValue: Int,\n    val optionalIntValue: Int?,\n    val booleanValue: Boolean,\n    val optionalBooleanValue: Boolean?\n)\n```\n\nWill be generated swift code that can be used like this:\n```swift\nlet newObj = dataClass.copy(\n    stringValue: {\"aNewValue\"}, \n    intValue: {1}, \n    booleanValue: {true}\n)\n```\n\n## Implementation of own generator\n\nFirst create `buildSrc`, if you don't. `build.gradle` will contains:\n\n```groovy\nplugins {\n    id(\"org.jetbrains.kotlin.jvm\") version \"1.6.10\"\n}\n\nrepositories {\n    mavenCentral()\n    google()\n    gradlePluginPortal()\n\n    maven(\"https://jitpack.io\")\n}\n\ndependencies {\n    implementation(\"com.android.tools.build:gradle:7.0.0\")\n    implementation(\"org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21\")\n    implementation(\"dev.icerock.moko:kswift-gradle-plugin:0.7.0\")\n}\n```\n\nThen in `buildSrc/src/main/kotlin` create `MyKSwiftGenerator`:\n\n```kotlin\nimport dev.icerock.moko.kswift.plugin.context.ClassContext\nimport dev.icerock.moko.kswift.plugin.feature.ProcessorContext\nimport dev.icerock.moko.kswift.plugin.feature.ProcessorFeature\nimport dev.icerock.moko.kswift.plugin.feature.BaseConfig\nimport dev.icerock.moko.kswift.plugin.feature.Filter\nimport io.outfoxx.swiftpoet.DeclaredTypeName\nimport io.outfoxx.swiftpoet.ExtensionSpec\nimport io.outfoxx.swiftpoet.FileSpec\nimport kotlin.reflect.KClass\n\n\nclass MyKSwiftGenerator(\n    override val featureContext: KClass\u003cClassContext\u003e,\n    override val filter: Filter\u003cClassContext\u003e\n) : ProcessorFeature\u003cClassContext\u003e() {\n    override fun doProcess(featureContext: ClassContext, processorContext: ProcessorContext) {\n        val fileSpec: FileSpec.Builder = processorContext.fileSpecBuilder\n        val frameworkName: String = processorContext.framework.baseName\n\n        val classSimpleName = featureContext.clazz.name.substringAfterLast('/')\n\n        fileSpec.addExtension(\n            ExtensionSpec\n                .builder(\n                    DeclaredTypeName.typeName(\"$frameworkName.$classSimpleName\")\n                )\n                .build()\n        )\n    }\n\n    class Config : BaseConfig\u003cClassContext\u003e {\n        override var filter: Filter\u003cClassContext\u003e = Filter.Exclude(emptySet())\n    }\n\n    companion object : Factory\u003cClassContext, MyKSwiftGenerator, Config\u003e {\n        override fun create(block: Config.() -\u003e Unit): MyKSwiftGenerator {\n            val config = Config().apply(block)\n            return MyKSwiftGenerator(featureContext, config.filter)\n        }\n\n        override val featureContext: KClass\u003cClassContext\u003e = ClassContext::class\n\n        @JvmStatic\n        override val factory = Companion\n    }\n}\n```\n\nin this example will be generated swift extension for each class in kotlin module. You can select\nrequired `Context` to got required info from klib metadata.\n\nlast step - enable feature in gradle:\n\nkotlin:\n```kotlin\nkswift {\n    install(MyKSwiftGenerator)\n}\n```\n\ngroovy:\n```groovy\nkswift {\n    install(MyKSwiftGenerator.factory)\n}\n```\n\n## Set iOS deployment target for podspec\n\nkotlin:\n```kotlin\nkswift {\n    iosDeploymentTarget.set(\"11.0\")\n}\n```\n\ngroovy:\n```groovy\nkswift {\n    iosDeploymentTarget = \"11.0\"\n}\n```\n\n# Samples\n\n- [branch regular-framework](https://github.com/Alex009/moko-kswift-usage-sample/tree/regular-framework) - how to use KSwift without cocoapods\n- [branch cocoapods](https://github.com/Alex009/moko-kswift-usage-sample/tree/cocoapods) - how to use KSwift with JetBrains CocoaPods plugin\n\n# FAQ\n\n## Where destination directory for all generated sources?\n\nSwift source code generates in same directory where compiles Kotlin/Native framework. In common case\nit directory\n`build/bin/{iosArm64 || iosX64}/{debugFramework || releaseFramework}/{frameworkName}Swift`.\n\nKotlin/Native cocoapods plugin (and also mobile-multiplatform cocoapods plugin by IceRock) will move\nthis sources into fixed directory - `build/cocoapods/framework/{frameworkName}Swift`.\n\n## How to exclude generation of entries from some libraries?\n\n```groovy\nkswift {\n    excludeLibrary(\"{libraryName}\")\n}\n```\n\n## How to generate entries only from specific libraries?\n\n```groovy\nkswift {\n    includeLibrary(\"{libraryName1}\")\n    includeLibrary(\"{libraryName2}\")\n}\n```\n\n# Samples\n\nMore examples can be found in the [sample directory](sample).\n\n# Set Up Locally\n\nClone project and just open it. Gradle plugin attached to sample by gradle composite build, so you\nwill see changes at each gradle build.\n\n```bash\n# clone repo\ngit clone git@github.com:icerockdev/moko-kswift.git\ncd moko-kswift \n# generate podspec files for cocopods intergration. with integration will be generated swift files for cocoapod\n./gradlew kSwiftmpp_library_podsPodspec\n./gradlew kSwiftMultiPlatformLibraryPodspec\n# go to ios dir\ncd sample/ios-app\n# install pods\npod install\n# now we can open xcworkspace and build ios project\nopen ios-app.xcworkspace\n# or run xcodebuild\nxcodebuild -scheme ios-app -workspace ios-app.xcworkspace test -destination \"platform=iOS Simulator,name=iPhone 12 mini\"\nxcodebuild -scheme pods-test -workspace ios-app.xcworkspace test -destination \"platform=iOS Simulator,name=iPhone 12 mini\"\n```\n\n# Contributing\n\nAll development (both new features and bug fixes) is performed in `develop` branch. This\nway `master` sources always contain sources of the most recently released version. Please send PRs\nwith bug fixes to `develop` branch. Fixes to documentation in markdown files are an exception to\nthis rule. They are updated directly in `master`.\n\nThe `develop` branch is pushed to `master` during release.\n\nMore detailed guide for contributers see in [contributing guide](CONTRIBUTING.md).\n\n# License\n\n    Copyright 2021 IceRock MAG Inc\n    \n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n    \n       http://www.apache.org/licenses/LICENSE-2.0\n    \n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficerockdev%2Fmoko-kswift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ficerockdev%2Fmoko-kswift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficerockdev%2Fmoko-kswift/lists"}