Is it possible to convert Kotlin generics to Swift Generics ?
At this time, it is converted to Any? (a.k.a Optional\
K/N does not interop with Swift directly yet, only via Objective-C, thus this feature request is not something we could help with at the moment.
yet and at the moment means it will be supported in the future?
It means I describe the current situation and cannot make any promises here.
I would also love to have this functionality. This would open a lot of cool possibilities for our team.
@olonho
I am currently evaluating whether or not we could use this project to build Android and iOS applications for our customers. The fact that we are basically unable to use generics in shared APIs or generics when calling into platform APIs (eg. UIViewController.subViews becoming a List<*> instead of List<UIView>) is a huge problem for us. I am sure this is a really, really hard problem and most likely there are no plans for this yet, but we really, really need this to build a solid framework for our applications (without a lot of boilerplate and type wrapping)
I must agree that generics visibility is an important part of interoperability. I believe that it is necessary if making common parts in Kotlin for Android and iOS is to become popular in mainstream programming.
Draft pull request generating generics in objc interop. Please comment if interested: https://github.com/JetBrains/kotlin-native/pull/2850
amazing
We need generics.
Kotlin Generics can be converted to ObjC/Swift Generics as of Kotlin 1.3.40
See https://blog.jetbrains.com/kotlin/2019/06/kotlin-1-3-40-released/
Yeah!
Kotlin Generics can be converted to ObjC/Swift Generics as of Kotlin 1.3.40
See https://blog.jetbrains.com/kotlin/2019/06/kotlin-1-3-40-released/
I haven't been able to make this work yet :( Currently I have this:
kotlin {
targets{
final def iOSTarget = System.getenv('SDK_NAME')?.startsWith("iphoneos") \
? presets.iosArm64 : presets.iosX64
fromPreset(iOSTarget, 'iOS') {
binaries {
framework('common') {
freeCompilerArgs.add("-Xobjc-generics")
But I still see Any? on my generic calls on the Xcode project, trying with iosX64 returns me the Cannot create binary debugFramework: binary with such a name already exists error, any tips, or any example on how to implement this correctly?
@desgraci this snippet is not enough to find the cause. Please post the entire Gradle script.
@SvyatoslavScherbina sure no problem:
//this is what makes this module a cool kotlin/native
apply plugin: 'kotlin-multiplatform'
//this is for using sqldelight
apply plugin: 'com.squareup.sqldelight'
//this is for sync with xcode
apply plugin: 'co.touchlab.kotlinxcodesync'
//this to work with pods
//https://github.com/JetBrains/kotlin-native/blob/master/COCOAPODS.md
apply plugin: 'org.jetbrains.kotlin.native.cocoapods'
version = "1.0"
apply plugin: 'kotlinx-serialization'
//region WIP
//WIP please consider using a delegate!
apply plugin: 'com.android.library'
android {
compileSdkVersion AndroidConfig.compileSdkVersion
defaultConfig {
minSdkVersion AndroidConfig.minSdkVersion
targetSdkVersion AndroidConfig.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
//This is for MultiplatformSettings
debug {
// MPP libraries don't currently get this resolution automatically
matchingFallbacks = ['release']
}
}
packagingOptions {
exclude 'META-INF/*.kotlin_module'
}
}
//endregion
// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
compileClasspath
}
sqldelight {
GymTrack {
packageName = "com.vonderful.gymtrack"
sourceFolders = ["sqldelight"]
//not needed now, but meh
schemaOutputDirectory = file("src/main/sqldelight/migrations")
}
}
kotlin {
targets {
targetFromPreset(presets.android, 'android')
final def iOSTarget = System.getenv('SDK_NAME')?.startsWith("iphoneos") \
? presets.iosArm64 : presets.iosX64
fromPreset(iOSTarget, 'iOS'){
compilations.main{
binaries {
framework("common") {
freeCompilerArgs.add("-Xobjc-generics")
}
}
}
}
}
sourceSets {
commonMain.dependencies {
implementation kotlin('stdlib-common')
//region Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib-common:${Versions.kotlin}"
//endregion
//region Coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:${Versions.kotlinCoroutines}"
//endregion
//region SQL Delight
implementation "com.squareup.sqldelight:runtime:${Versions.sqlDelight}"
// implementation "com.squareup.sqldelight:coroutines-extensions:${Versions.sqlDelight}"
//endregion
//region di
implementation "org.kodein.di:kodein-di-erased:${Versions.kodein}"
//endregion
//https://github.com/Kotlin/kotlinx.serialization
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:0.13.0"
implementation "io.ktor:ktor-client-core:${Versions.ktor}"
implementation "io.ktor:ktor-client-json:${Versions.ktor}"
implementation "io.ktor:ktor-client-serialization:${Versions.ktor}"
}
commonTest.dependencies {
implementation 'org.jetbrains.kotlin:kotlin-test-common'
implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
}
//If you want to don't share the libs, don't use this and do your own imports on the dependencies...
configure([androidMain]) {
dependsOn commonMain
}
androidMain.dependencies {
//region Coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.kotlinCoroutines}"
//implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.kotlinCoroutines}"
//endregion
//region SQL Delight
implementation "com.squareup.sqldelight:android-driver:${Versions.sqlDelight}"
//implementation "com.squareup.sqldelight:coroutines-extensions-jvm:${Versions.sqlDelight}"
//endregion
// The base will compile ok, but when ran, it will fail with an unresolveded reference
// so we add this
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:${Versions.serializationRuntime}"
//same we ktor, we are just sending those scary messages away!
implementation "io.ktor:ktor-client-android:${Versions.ktor}"
implementation "io.ktor:ktor-client-json-jvm:${Versions.ktor}"
implementation "io.ktor:ktor-client-serialization-jvm:${Versions.ktor}"
}
androidTest.dependencies{
implementation 'org.jetbrains.kotlin:kotlin-test'
implementation 'org.jetbrains.kotlin:kotlin-test-junit'
implementation "com.squareup.sqldelight:sqlite-driver:${Versions.sqlDelight}"
}
configure([iOSMain]) {
dependsOn commonMain
}
iOSMain.dependencies {
//region Coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:${Versions.kotlinCoroutines}"
//endregion
//region SQL Delight
implementation "com.squareup.sqldelight:ios-driver:${Versions.sqlDelight}"
//endregion
//same as in Android
implementation "io.ktor:ktor-client-ios:${Versions.ktor}"
implementation "io.ktor:ktor-client-json-native:${Versions.ktor}"
implementation"org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:${Versions.serializationRuntime}"
implementation "io.ktor:ktor-client-serialization-native:${Versions.ktor}"
}
}
// //run the podscpec if you don't see the podspec :p !
cocoapods {
// Configure fields required by CocoaPods.
summary = "Library for GymTrack app"
homepage = "https://po.ta.to"
}
}
xcode {
projectPath = "../ios/Gym Track/Gym Track.xcodeproj"
target = "Gym Track"
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
jvmTarget = "1.8"
}
}
task copyFramework {
def buildType = project.findProperty('kotlin.build.type') ?: 'DEBUG'
def target = project.findProperty('kotlin.target') ?: 'iOS'
//looking for commonDebugFramework
dependsOn kotlin.targets."$target".binaries.getFramework("common", 'DEBUG').linkTask
//arstDebugFramework
doLast {
def srcFile = kotlin.targets."$target".compilations.main.getBinary('FRAMEWORK', buildType)
def targetDir = getProperty('configuration.build.dir')
copy {
from srcFile.parent
into targetDir
include 'app.framework/**'
include 'app.framework.dSYM'
}
}
}
I've tried different combinations so far, but no luck, if there is anything else that I can bring to the table to help ouy let me know, btw this is my test generic class:
data class GenericTestData<T : Any>(val t: T)
but I still get the @interface SharecodeGenericTestData without the <T> at Swift
CocoaPods plugin creates its own framework internally.
Your snippet
framework("common") {
freeCompilerArgs.add("-Xobjc-generics")
}
creates the second one. It should configure already created framework instead. Please refer to the documentation (see "Accessing binaries").
Indeed, wasn't overwriting in the correct way the cocoapod's framework, worked like a charm, a good case of RTFabolousM, thank you for guiding me on this one @SvyatoslavScherbina
Hi, maybe you can help me. I followed this tutorial: https://medium.com/@fandygotama/kotlin-multiplatform-reactive-a45263e1fd7a and got tuck right in the beginning. The sync fails:
Build file '/myPath/kmmmovies/core/build.gradle' line: 16
A problem occurred evaluating project ':core'.
> Operation is not supported for read-only collection
line 16 is the freeCompilerArgs.add("-Xobjc-generics"):
fromPreset(iOSTarget, 'iOS') {
binaries {
framework("core") {
freeCompilerArgs.add("-Xobjc-generics")
}
}
Can anyone tells me what am I doing wrong?
Most helpful comment
@olonho
I am currently evaluating whether or not we could use this project to build Android and iOS applications for our customers. The fact that we are basically unable to use generics in shared APIs or generics when calling into platform APIs (eg. UIViewController.subViews becoming a
List<*>instead ofList<UIView>) is a huge problem for us. I am sure this is a really, really hard problem and most likely there are no plans for this yet, but we really, really need this to build a solid framework for our applications (without a lot of boilerplate and type wrapping)