How to add an Apple dependency to a Kotlin/Native module with Gradle in a Kotlin/Native or Kotlin Multiplatform project?
I am not familiar with Apple and Xcode development—I have written a little bit of Swift but haven't configured extra dependencies for an Xcode project, so excuse me if I am having rookie misconceptions here.
Kotlin/Native is interoperable with Objective-C and Swift. In a lot of sample projects I have browsed online, Kotlin is set to be used as a shared library for the Apple (iOS) module. but It should also make sense that definitions in Apple dependencies can be called from Kotlin code, like how Java Maven dependencies can be added to the Gradle build script and then called by Kotlin code.
In the Name Translation section it's said:
platform.*
packages for preconfigured system frameworks
In a project created with the Kotlin Multiplatform Mobile Application option in IntelliJ IDEA, such definitions are included under the platform
package in the iosMain
module's kotlin
folder in the shared
module.
However, SwiftUI is not there. And more specifically in my case, I am trying to build UIs directly in Kotlin with SwiftUI. Is it currently possible and then how do I make the SwiftUI "system framework" also included?
Here is my build.gradle.kts
in the shared
module for reference:
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform") version "1.4.30"
}
group = "my.group.name"
version = "1.0-SNAPSHOT"
kotlin {
ios {
binaries {
framework {
baseName = "shared"
}
}
}
sourceSets {
val commonMain by getting
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val iosMain by getting
val iosTest by getting
}
}
val packForXcode by tasks.creating(Sync::class) {
group = "build"
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
val framework = kotlin.targets.getByName<KotlinNativeTarget>(targetName).binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-frameworks")
from({ framework.outputDirectory })
into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)
Kotlin/Native does not interop with pure Swift. From the doc you linked:
"Kotlin/Native provides bidirectional interoperability with Objective-C" ... "A Swift library can be used in Kotlin code if its API is exported to Objective-C with @objc. Pure Swift modules are not yet supported."
Swift can be written to interop with Objc, using the @objc
Swift annotation, which will apply some constraints to the Swift code. Pure Swift, which SwiftUI definitely is, cannot be imported into Kotlin.
I would also suggest that even if possible, coding SwiftUI from Kotlin would likely be a far worse dev experience, as Xcode has had a lot of work put into enabling SwiftUI previews, etc. If there's ever any formal effort for a Kotlin UI for iOS, I would guess it'll be an attempt at Compose. It's possible JetBrains will put some effort towards SwiftUI in AppCode, but I would guess it'll be a long time before that happens for SwiftUI + Kotlin. Kotlin/Native would first need direct Swift interop, which has been discussed but AFAIK, hasn't been started.
Summary, I'd code SwiftUI in Xcode with Swift and just talk to the other shared Kotlin for logic "below" the UI.