moko-kswift - Gradle-плагин, разработанный командой IceRock, для генерации Swift-friendly кода для Kotlin/Native.
Фича Kotlin-а | Ожидание | Статус | Комментарий |
---|---|---|---|
sealed-класс | Сгенерируется bridge-код для перевода класса в enum | ✅ | Всё ок 👍 |
sealed-класс с глубокой иерархией | Сгенерируется bridge-код для перевода в один enum | Генерируется по enum-у для каждого sealed-класса вместо одного | |
sealed-интерфейс | Сгенерируется bridge-код для перевода в enum | ✅ | Всё ок (y) |
extension function over platform class | Сгенерируется extension на стороне Swift-а | Платформенные классы - это классы из пакета platform.* |
Допустим, была вот такая иерархия классов:
sealed class SealedWithDeepHierarchy {
abstract val param: String
sealed class LocalTrigger : SealedWithDeepHierarchy() {
object First : LocalTrigger() {
override val param: String = "first"
}
}
sealed class RemoteTrigger : SealedWithDeepHierarchy() {
class Second(override val param: String) : RemoteTrigger()
data class Third(override val param: String) : RemoteTrigger()
}
}
На стороне Kotlin-а такие классы очень удобно разворачивать внутри when-выражения:
private fun example(s: SealedWithDeepHierarchy) {
when (s) {
SealedWithDeepHierarchy.LocalTrigger.First -> TODO()
is SealedWithDeepHierarchy.RemoteTrigger.Second -> TODO()
is SealedWithDeepHierarchy.RemoteTrigger.Third -> TODO()
}
}
С moko-swift сгенерировался вот такой swift-код:
public enum SealedWithDeepHierarchyLocalTriggerKs {
case first
public init(_ obj: SealedWithDeepHierarchy.LocalTrigger) {
if obj is HHMobileSdk.SealedWithDeepHierarchy.LocalTriggerFirst {
self = .first
} else {
fatalError("SealedWithDeepHierarchyLocalTriggerKs not syncronized with SealedWithDeepHierarchy.LocalTrigger class")
}
}
}
public enum SealedWithDeepHierarchyRemoteTriggerKs {
case second(SealedWithDeepHierarchy.RemoteTriggerSecond)
case third(SealedWithDeepHierarchy.RemoteTriggerThird)
public init(_ obj: SealedWithDeepHierarchy.RemoteTrigger) {
if let obj = obj as? HHMobileSdk.SealedWithDeepHierarchy.RemoteTriggerSecond {
self = .second(obj)
} else if let obj = obj as? HHMobileSdk.SealedWithDeepHierarchy.RemoteTriggerThird {
self = .third(obj)
} else {
fatalError("SealedWithDeepHierarchyRemoteTriggerKs not syncronized with SealedWithDeepHierarchy.RemoteTrigger class")
}
}
}
public enum SealedWithDeepHierarchyKs {
case localTrigger(SealedWithDeepHierarchy.LocalTrigger)
case remoteTrigger(SealedWithDeepHierarchy.RemoteTrigger)
public init(_ obj: SealedWithDeepHierarchy) {
if let obj = obj as? HHMobileSdk.SealedWithDeepHierarchy.LocalTrigger {
self = .localTrigger(obj)
} else if let obj = obj as? HHMobileSdk.SealedWithDeepHierarchy.RemoteTrigger {
self = .remoteTrigger(obj)
} else {
fatalError("SealedWithDeepHierarchyKs not syncronized with SealedWithDeepHierarchy class")
}
}
}
И соответственно, использовать это можно вот так:
func mokoKswiftUsage(c: SealedWithDeepHierarchy) {
switch SealedWithDeepHierarchyKs(c) {
case let .localTrigger(tr):
switch SealedWithDeepHierarchyLocalTriggerKs(tr) {
case .first:
<#code#>
}
case let .remoteTrigger(tr):
switch SealedWithDeepHierarchyRemoteTriggerKs(tr) {
case .second(_):
<#code#>
case .third(_):
<#code#>
}
}
}
Для большего удобства хорошо бы иметь единый enum.
Ожидал, что это сработает для любого платформенного класса.
Мы считаем платформенными классами любые классы типов (String / Int / Boolean / etc) + какие-то специфичные платформенные
(тот же platform.UIKit.UILabel
для iOS).
Но оказалось, что учитываются только платформенные, у которых в package name-е 3 части,
первая из которых равна platform
.
Поэтому для fun String.myExtensionFunction()
маппинг не сработал.