Closed zhuyifan2013 closed 1 year ago
I founded the generated codes for this :
@ObjCName(name = "login")
public fun IUserRepository.loginNative(loginRequest: IUserRepository.LoginRequest):
NativeFlow<APIResult> = login(loginRequest).asNativeFlow(null)
But seems this generated file is not founded by Swift
This is my shared
setting:
plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
kotlin("plugin.serialization") version "1.8.10"
id("com.google.devtools.ksp") version "1.8.20-1.0.10" apply (true)
id("com.rickclephas.kmp.nativecoroutines") version "1.0.0-ALPHA-6"
id("com.android.library")
}
val packageName = "com.yifan.fallinlove"
val ktorVersion = "2.1.3"
val ktCoroutineVersion = "1.6.4"
val apolloVersion = "3.6.2"
val koinVersion = "3.2.2"
val koinKtor = "3.2.2"
//val koinKspVersion = "1.0.3"
val sqlDelightVersion = "1.5.3"
//val kspCompiler = "io.insert-koin:koin-ksp-compiler:${koinKspVersion}"
val napierVersion = "2.6.1"
kotlin {
android()
iosX64()
iosArm64()
iosSimulatorArm64()
cocoapods {
summary = "Some description for the Shared Module"
homepage = "Link to the Shared Module homepage"
version = "0.1.1"
ios.deploymentTarget = "14.1"
podfile = project.file("../iosApp/Podfile")
framework {
baseName = "shared"
isStatic = false
}
}
sourceSets {
all {
languageSettings.optIn("kotlin.RequiresOptIn")
languageSettings.optIn("kotlin.experimental.ExperimentalObjCName")
}
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$ktCoroutineVersion")
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1")
implementation("io.insert-koin:koin-core:$koinVersion")
implementation(libs.kotlinx.serialization.properties)
implementation(libs.androidx.dataStore.preferences.core)
implementation("io.github.aakira:napier:$napierVersion")
// implementation("com.google.devtools.ksp:symbol-processing-api:1.8.20-1.0.10")
api("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
api("androidx.datastore:datastore-core-okio:1.1.0-dev01")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val androidMain by getting {
dependencies {
implementation("io.ktor:ktor-client-android:$ktorVersion")
}
}
val androidTest by getting
val iosX64Main by getting
val iosArm64Main by getting
val iosSimulatorArm64Main by getting
val iosMain by creating {
dependsOn(commonMain)
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)
dependencies {
implementation("io.ktor:ktor-client-darwin:$ktorVersion")
}
}
val iosX64Test by getting
val iosArm64Test by getting
val iosSimulatorArm64Test by getting
val iosTest by creating {
dependsOn(commonTest)
iosX64Test.dependsOn(this)
iosArm64Test.dependsOn(this)
iosSimulatorArm64Test.dependsOn(this)
}
}
}
android {
namespace = packageName
compileSdk = 33
defaultConfig {
minSdk = 29
targetSdk = 33
}
}
//dependencies {
// add("kspCommonMainMetadata", kspCompiler)
// add("kspAndroid", kspCompiler)
// add("kspIosX64", kspCompiler)
// add("kspIosSimulatorArm64", kspCompiler)
//}
kotlin.targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget::class.java) {
binaries.all {
binaryOptions["memoryModel"] = "experimental"
}
}
Hi! I am assuming that IUserRepository
is an interface, right?
In that case you are seeing a limitation of the Objective-C interop, where extensions on interfaces/protocols aren't supported.
Such extensions are exposed on a Kt
object instead.
Assuming your file is also called IUserRepository
you should be able to access the extension function with:
let repo: IUserRepository
let loginRequest: IUserRepository.LoginRequest
let nativeFlow = IUserRepositoryNativeKt.login(repo, loginRequest: loginRequest)
To make this easier to work with you could define an extension in Swift:
extension IUserRepository {
func login(loginRequest: IUserRepository.LoginRequest) -> AnyPublisher<APIResult, Error> {
return createPublisher(for: IUserRepositoryNativeKt.login(self, loginRequest: loginRequest))
}
}
In this case I used the createPublisher(for:)
function from the Combine implementation, but you could obviously use any Swift implementation you like.
I will take a look at the documentation to make sure these limitations are better documented.
@rickclephas I have the same issue in version 1.0.0-ALPHA-4
When I annotate a stateflow with @NativeCoroutinesState it won't be visible on the iOS side anymore.
I'm using it in my shared view models which are classes, not interfaces.
@hosseinaminii could you possibly share some of the affected code? Are you using multiple Kotlin modules or just a single shared
module?
@rickclephas The project has 3 KMM modules which are data, domain, and shared(The shared module has access to the data and domain modules). We use the shared module to share view models which iOS and Android have access to it and I added this library to this module. Also, I added the KMPNativeCoroutinesAsync library to the pods and installed it. Everything was straightforward and there was no problem in adding the library to the project but unfortunately, it has the mentioned issue.
Hi @rickclephas , thanks for figuring out, but there is still a problem that confuses me, what is the return type for this ?
The generated code is :
@ObjCName(name = "login")
public fun IUserRepository.loginNative(loginRequest: IUserRepository.LoginRequest):
NativeFlow<APIResult> = login(loginRequest).asNativeFlow(null)
And the original interface definition is :
@NativeCoroutines
fun login(loginRequest: LoginRequest): Flow<APIResult>
@hosseinaminii alright that sound like a setup that should be supported. Could you possibly share a minimum reproducible sample?
@zhuyifan2013 in that case your login
function should have the following return type: NativeFlowAsyncSequence< APIResult, Error, KotlinUnit>
.
@rickclephas Ok, I'll try to create a sample project as soon as possible and share it with you. Thank you
@rickclephas Yes, it works, thanks very much!!
@rickclephas The project has 3 KMM modules which are data, domain, and shared(The shared module has access to the data and domain modules). We use the shared module to share view models which iOS and Android have access to it and I added this library to this module. Also, I added the KMPNativeCoroutinesAsync library to the pods and installed it. Everything was straightforward and there was no problem in adding the library to the project but unfortunately, it has the mentioned issue.
@hosseinaminii Can't see that you got a suggestion on how to resolve this issue? Previously we could access state of StateFlow by a generated value called stateNative, but it is no longer generated. How did you resolve this?
@hhpettersen in the 1.0 releases the native suffix has been removed. So a StateFlow
property called state
would have a stateValue
(or state
when using the @NativeCoroutinesState
annotation) property that exposes the value of the StateFlow.
After upgrading to 1.x from 0.x, some functions could not work in Swift:
Codes like this, do I need to add @NativeCoroutines to it ? If I added, I could not find this method in Swift, if not, this also could be called properly.