• Stars
    star
    335
  • Rank 121,813 (Top 3 %)
  • Language
    Kotlin
  • License
    Apache License 2.0
  • Created almost 3 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Swift-friendly api generator for Kotlin/Native frameworks

moko-kswift
GitHub license Download kotlin-version

MOKO KSwift

KSwift it's gradle plugin for generation Swift-friendly API for Kotlin/Native framework.

Kotlin sealed interface/class to Swift enum

sealed classes compare

Kotlin extensions for K/N platform classes

extensions compare

Your own case

KSwift give you API for adding your own generator based on KLib metadata information.

Posts

Table of Contents

Features

  • API for extend logic for own cases - just implement your own ProcessorFeature
  • Reading of all exported klibs - you can generate swift additions to the api of external libraries
  • Kotlin sealed class/interface to Swift enum
  • Kotlin extensions for platform classes to correct extensions instead of additional class with static methods
  • Flexible filtration - select what you want to generate and what not

Requirements

  • Gradle version 6.0+
  • Kotlin 1.6.10

Installation

Plugin

Using legacy plugin application

root build.gradle

buildscript {
    repositories {
        mavenCentral()
        google()
        gradlePluginPortal()
    }
    dependencies {
        classpath("dev.icerock.moko:kswift-gradle-plugin:0.6.1")
    }
}

project where framework compiles build.gradle

plugins {
    id("dev.icerock.moko.kswift")
}

Using the plugins DSL

settings.gradle

pluginManagement {
    repositories {
        google()
        gradlePluginPortal()
        mavenCentral()
    }
}

project where framework compiles build.gradle

plugins {
    id("dev.icerock.moko.kswift") version "0.6.1"
}

Runtime library

root build.gradle

allprojects {
    repositories {
        mavenCentral()
    }
}

project build.gradle

dependencies {
    commonMainApi("dev.icerock.moko:kswift-runtime:0.6.1") // if you want use annotations
}

Usage

Xcode configuration

The Swift code generated from this plugin is not automatically included in the shared framework you might have.

You have 2 options to use it in your iOS project:

  • Xcode direct file integration
  • CocoaPods integration

Xcode direct file integration

You can directly import the generated file in your Xcode project like it's a file you have written on your own.

To do so:

  • open the Xcode project
  • right click on "iosApp"
  • choose "Add files to iOSApp"
  • add the file from the generated folder (you might need to read the FAQ to know where the generated folder is)
  • you are now good to go!

CocoaPods integration

After 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).

  • Run the task doing ./gradlew kSwiftsharedPodspec from the root of your project. This will generate a new podspec file, XXXXXSwift.podspec, where XXXXX is still the name of your shared module (so e.g. sharedSwift.podspec)

  • Now edit the Podfile inside the iOS project adding this line pod 'sharedSwift', :path => '../shared' just after the one already there for the already available shared module pod 'shared', :path => '../shared'

  • Now run pod install from the iosApp folder so the new framework is linked to your project.

  • 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!

Sealed classes/interfaces to Swift enum

Enable feature in project build.gradle:

kotlin:

kswift {
    install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature)
}

groovy:

kswift {
    install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature.factory)
}

That's all - after this setup all sealed classes and sealed interfaces will be parsed by plugin and plugin will generate Swift enums for this classes.

For example if you have in your kotlin code:

sealed interface UIState<out T> {
    object Loading : UIState<Nothing>
    object Empty : UIState<Nothing>
    data class Data<T>(val value: T) : UIState<T>
    data class Error(val throwable: Throwable) : UIState<Nothing>
}

Then plugin will generate source code:

/**
 * selector: ClassContext/moko-kswift.sample:mpp-library-pods/com/icerockdev/library/UIState */
public enum UIStateKs<T : AnyObject> {

  case loading
  case empty
  case data(UIStateData<T>)
  case error(UIStateError)

  public init(_ obj: UIState) {
    if obj is shared.UIStateLoading {
      self = .loading
    } else if obj is shared.UIStateEmpty {
      self = .empty
    } else if let obj = obj as? shared.UIStateData<T> {
      self = .data(obj)
    } else if let obj = obj as? shared.UIStateError {
      self = .error(obj)
    } else {
      fatalError("UIStateKs not syncronized with UIState class")
    }
  }

}

For each generated entry in comment generated selector - value of this selector can be used for filter. By default all entries generated. But if generated code invalid (please report issue in this case) you can disable generation of this particular entry:

kotlin:

kswift {
    install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature) {
        filter = excludeFilter("ClassContext/moko-kswift.sample:mpp-library-pods/com/icerockdev/library/UIState")
    }
}

groovy:

kswift {
    install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature.factory) {
        it.filter = it.excludeFilter("ClassContext/moko-kswift.sample:mpp-library-pods/com/icerockdev/library/UIState")
    }
}

As alternative you can use includeFilter to explicit setup each required for generation entries:

kotlin:

kswift {
    install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature) {
        filter = includeFilter("ClassContext/moko-kswift.sample:mpp-library-pods/com/icerockdev/library/UIState")
    }
}

groovy:

kswift {
    install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature.factory) {
        it.filter = it.includeFilter("ClassContext/moko-kswift.sample:mpp-library-pods/com/icerockdev/library/UIState")
    }
}

Extensions from platform classes

Enable feature in project build.gradle:

kotlin:

kswift {
    install(dev.icerock.moko.kswift.plugin.feature.PlatformExtensionFunctionsFeature)
}

groovy:

kswift {
    install(dev.icerock.moko.kswift.plugin.feature.PlatformExtensionFunctionsFeature.factory)
}

That's all - after this setup all extension functions for classes from platform.* package will be correct swift code.

For example if you have in your kotlin code:

class CFlow<T>(private val stateFlow: StateFlow<T>) : StateFlow<T> by stateFlow

fun UILabel.bindText(coroutineScope: CoroutineScope, flow: CFlow<String>) {
    val label = this
    coroutineScope.launch {
        label.text = flow.value
        flow.collect { label.text = it }
    }
}

Then plugin will generate source code:

public extension UIKit.UILabel {
  /**
   * 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)<Class(name=kotlin/String)> */
  public func bindText(coroutineScope: CoroutineScope, flow: CFlow<NSString>) {
    return UILabelExtKt.bindText(self, coroutineScope: coroutineScope, flow: flow)
  }
}

Selector from comment can be used for filters as in first example.

Implementation of own generator

First create buildSrc, if you don't. build.gradle will contains:

plugins {
    id("org.jetbrains.kotlin.jvm") version "1.6.10"
}

repositories {
    mavenCentral()
    google()
    gradlePluginPortal()

    maven("https://jitpack.io")
}

dependencies {
    implementation("com.android.tools.build:gradle:7.0.0")
    implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21")
    implementation("dev.icerock.moko:kswift-gradle-plugin:0.2.0")
}

Then in buildSrc/src/main/kotlin create MyKSwiftGenerator:

import dev.icerock.moko.kswift.plugin.context.ClassContext
import dev.icerock.moko.kswift.plugin.feature.ProcessorContext
import dev.icerock.moko.kswift.plugin.feature.ProcessorFeature
import dev.icerock.moko.kswift.plugin.feature.BaseConfig
import dev.icerock.moko.kswift.plugin.feature.Filter
import io.outfoxx.swiftpoet.DeclaredTypeName
import io.outfoxx.swiftpoet.ExtensionSpec
import io.outfoxx.swiftpoet.FileSpec
import kotlin.reflect.KClass


class MyKSwiftGenerator(
    override val featureContext: KClass<ClassContext>,
    override val filter: Filter<ClassContext>
) : ProcessorFeature<ClassContext>() {
    override fun doProcess(featureContext: ClassContext, processorContext: ProcessorContext) {
        val fileSpec: FileSpec.Builder = processorContext.fileSpecBuilder
        val frameworkName: String = processorContext.framework.baseName

        val classSimpleName = featureContext.clazz.name.substringAfterLast('/')

        fileSpec.addExtension(
            ExtensionSpec
                .builder(
                    DeclaredTypeName.typeName("$frameworkName.$classSimpleName")
                )
                .build()
        )
    }

    class Config : BaseConfig<ClassContext> {
        override var filter: Filter<ClassContext> = Filter.Exclude(emptySet())
    }

    companion object : Factory<ClassContext, MyKSwiftGenerator, Config> {
        override fun create(block: Config.() -> Unit): MyKSwiftGenerator {
            val config = Config().apply(block)
            return MyKSwiftGenerator(featureContext, config.filter)
        }

        override val featureContext: KClass<ClassContext> = ClassContext::class

        @JvmStatic
        override val factory = Companion
    }
}

in this example will be generated swift extension for each class in kotlin module. You can select required Context to got required info from klib metadata.

last step - enable feature in gradle:

kotlin:

kswift {
    install(MyKSwiftGenerator)
}

groovy:

kswift {
    install(MyKSwiftGenerator.factory)
}

Set iOS deployment target for podspec

kotlin:

kswift {
    iosDeploymentTarget.set("11.0")
}

groovy:

kswift {
    iosDeploymentTarget = "11.0"
}

Samples

FAQ

Where destination directory for all generated sources?

Swift source code generates in same directory where compiles Kotlin/Native framework. In common case it directory build/bin/{iosArm64 || iosX64}/{debugFramework || releaseFramework}/{frameworkName}Swift.

Kotlin/Native cocoapods plugin (and also mobile-multiplatform cocoapods plugin by IceRock) will move this sources into fixed directory - build/cocoapods/framework/{frameworkName}Swift.

How to exclude generation of entries from some libraries?

kswift {
    excludeLibrary("{libraryName}")
}

How to generate entries only from specific libraries?

kswift {
    includeLibrary("{libraryName1}")
    includeLibrary("{libraryName2}")
}

Samples

More examples can be found in the sample directory.

Set Up Locally

Clone project and just open it. Gradle plugin attached to sample by gradle composite build, so you will see changes at each gradle build.

# clone repo
git clone [email protected]:icerockdev/moko-kswift.git
cd moko-kswift 
# generate podspec files for cocopods intergration. with integration will be generated swift files for cocoapod
./gradlew kSwiftmpp_library_podsPodspec
./gradlew kSwiftMultiPlatformLibraryPodspec
# go to ios dir
cd sample/ios-app
# install pods
pod install
# now we can open xcworkspace and build ios project
open ios-app.xcworkspace
# or run xcodebuild
xcodebuild -scheme ios-app -workspace ios-app.xcworkspace test -destination "platform=iOS Simulator,name=iPhone 12 mini"
xcodebuild -scheme pods-test -workspace ios-app.xcworkspace test -destination "platform=iOS Simulator,name=iPhone 12 mini"

Contributing

All development (both new features and bug fixes) is performed in develop branch. This way master sources always contain sources of the most recently released version. Please send PRs with bug fixes to develop branch. Fixes to documentation in markdown files are an exception to this rule. They are updated directly in master.

The develop branch is pushed to master during release.

More detailed guide for contributers see in contributing guide.

License

Copyright 2021 IceRock MAG Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

More Repositories

1

moko-mvvm

Model-View-ViewModel architecture components for mobile (android & ios) Kotlin Multiplatform development
Kotlin
951
star
2

moko-resources

Resources access for mobile (android & ios) Kotlin Multiplatform development
Kotlin
945
star
3

moko-template

Template project of a Mobile (Android & iOS) Kotlin MultiPlatform project with the MOKO libraries and modularized architecture
Kotlin
452
star
4

moko-widgets

Multiplatform UI DSL with screen management in common code for mobile (android & ios) Kotlin Multiplatform development
Kotlin
363
star
5

moko-permissions

Runtime permissions controls for mobile (android & ios) Kotlin Multiplatform development
Kotlin
249
star
6

libs.kmp.icerock.dev

Kotlin Multiplatform libraries list with info auto-fetch
JavaScript
229
star
7

moko-network

Network components with codegeneration of rest api for mobile (android & ios) Kotlin Multiplatform development
Kotlin
147
star
8

moko-geo

Geolocation access for mobile (android & ios) Kotlin Multiplatform development
Kotlin
113
star
9

moko-socket-io

MOKO SocketIo by IceRock is Socket.IO implementation Kotlin Multiplatform library
Kotlin
93
star
10

mobile-multiplatform-gradle-plugin

Gradle plugin for simplify Kotlin Multiplatform mobile configurations
Kotlin
92
star
11

moko-maps

Control your map from common code for mobile (android & ios) Kotlin Multiplatform development
Kotlin
71
star
12

moko-media

Media selection & presenting for mobile (android & ios) Kotlin Multiplatform development
Kotlin
66
star
13

moko-parcelize

@Parcelize support for mobile (android & ios) Kotlin Multiplatform development
Kotlin
60
star
14

moko-paging

Pagination logic in common code for mobile (android & ios) Kotlin Multiplatform development
Kotlin
57
star
15

moko-errors

Automated exceptions handler for mobile (android & ios) Kotlin Multiplatform development.
Kotlin
52
star
16

moko-web3

Ethereum Web3 implementation for mobile (android & ios) Kotlin Multiplatform development
Kotlin
41
star
17

moko-biometry

Biometry authentication with Touch ID, Face ID from common code with Kotlin Multiplatform Mobile
Kotlin
34
star
18

moko-crash-reporting

Fatal and Non-Fatal reporting to Crashlytics for Kotlin Multiplatform Mobile
Kotlin
26
star
19

moko-units

Composing units into list and show in RecyclerView/UITableView/UICollectionView. Control your lists from common code for mobile (android & ios) Kotlin Multiplatform development
Kotlin
25
star
20

kmm.icerock.dev

JavaScript
22
star
21

redwood-sample

Kotlin
21
star
22

moko-fields

Input forms for mobile (android & ios) Kotlin Multiplatform development
Kotlin
19
star
23

moko-graphics

Graphics primitives for mobile (android & ios) Kotlin Multiplatform development
Kotlin
16
star
24

moko-javascript

JavaScript evaluation from kotlin common code for android & iOS
Kotlin
14
star
25

moko-tensorflow

Tensorflow Lite bindings for mobile (android & ios) Kotlin Multiplatform development
Kotlin
14
star
26

moko-core

Core classes for mobile (android & ios) Kotlin Multiplatform development
Kotlin
13
star
27

shaper

File structure generation tool from templates on Handlebars
Kotlin
12
star
28

moko-test

Test utilities for mobile (android & ios) Kotlin Multiplatform development
Kotlin
11
star
29

moko-widgets-template

Template project of a Mobile (Android & iOS) Kotlin MultiPlatform project with the MOKO widgets and other MOKO libs
Kotlin
10
star
30

kotlin-version-badge

badge with kotlin version, automatically fetched from mavenCentral package of latest version
Kotlin
10
star
31

moko

MOKO libraries umbrella project
Kotlin
9
star
32

gpuimage-filters-editor

iPad application photo editor with filters by GPUImage
Objective-C
9
star
33

codelabs.kmp.icerock.dev

Education of Kotlin Multiplatform Mobile
JavaScript
8
star
34

mobile-multiplatform-education

Internal lessons of mobile multiplatform development
Kotlin
8
star
35

email-service

Email sending service for kotlin - part of BOKO libs
Kotlin
7
star
36

moko.icerock.dev

Home page of moko libraries
HTML
7
star
37

moko-doctor

doctor script for checking the KMM developer's environment
Shell
6
star
38

admin-toolkit

Toolkit to create admin panels - part of BOKO libs
TypeScript
6
star
39

binance-futures-kotlin-api

Kotlin
6
star
40

sms-service

Sms sending service for kotlin - part of BOKO libs
Kotlin
5
star
41

storage-service

Tools for work with s3 storage and generate preview - part of BOKO libs
Kotlin
5
star
42

fcm-push-service

Tools for sending fcm push by kotlin - part of BOKO libs
Kotlin
5
star
43

yellowdoor-app

Kotlin
4
star
44

prototyping.icerock.dev

JavaScript
4
star
45

moko-time

Timestamp and timers for mobile (android & ios) Kotlin Multiplatform development
Kotlin
4
star
46

moko-gradle-plugin

Kotlin
3
star
47

moko-utils

Utilities for mobile (android & ios) Kotlin Multiplatform development
Kotlin
3
star
48

db-utils

Common tools for work with postgres via exposed - part of BOKO libs
Kotlin
3
star
49

web-utils

Common tools for create web application (ktor based) - part of BOKO libs
Kotlin
3
star
50

tinkoff-merchant-api

Tinkoff Merchant API Kotlin Client - part of BOKO libs
Kotlin
3
star
51

moko-intellij-plugin

Kotlin
3
star
52

slackbot-gitlab-ci

GitLab CI slackbot (beepboophq.com version)
JavaScript
2
star
53

auth-service

Common tools for JWT auth - part of BOKO libs
Kotlin
2
star
54

icerock-talaiot-config-plugin

Kotlin
2
star
55

PopupBottomNavigation

Popup menu with additional tabs for UITabBarController
Swift
2
star
56

IRPDFKit

PDF viewer with search for iOS
JavaScript
2
star
57

kafka-service

Common tools for kafka - part of BOKO libs
Kotlin
2
star
58

boko-validation

Konform based validation for Kotlin/JVM - part of BOKO libs
Kotlin
2
star
59

delivery.icerock.dev

Handlebars
1
star
60

shaper-templates

Templates for Shaper generation tool
Handlebars
1
star
61

kmp.icerock.dev

Kotlin Mobile MultiPlatform materials landing
HTML
1
star