KMM - 无法快速铸造密封类/接口

发布于 2025-01-20 03:26:49 字数 1432 浏览 1 评论 0原文

在我的KMM库中,我使用密封的接口/类来表示某些状态/错误。 我决定使用密封接口/类,因为这些状态必须具有不同的相关对象。

在Android代码中,这也可以按预期工作,没有任何问题。

但是在iOS部分中,我无法检测到特定状态,因为演员表是不可能的。

该错误独立于它是密封接口还是密封类是一个示例:

sealed class SyncState() {
    object Loading : SyncState()
    data class Active(val syncNumber: String) : SyncState()
    data class Error(val throwable: Throwable) : SyncState()
}

在KMM库中的存储库中,现在根据状态返回相应的Syncstate。

fun currentSyncState(): SyncState {
    if … {
        return SyncState.Error(Throwable("…"))
    } else if … {
        return SyncState.Active("…")
    } else {
        return SyncState.Loading
    }
}

在iOS中,我也可以在没有任何问题的情况下调用此功能。 唯一的问题是,我无法分辨出从返回的对象的哪个状态,因为铸件在任何时候都无法使用。

let state = repo.currentSyncState()
…

(lldb) po state
SyncState.Loading@2fe538

(lldb) po state is SyncState
true

(lldb) po state is SyncState.Loading
false

(lldb) po type(of: state)
SyncStateLoading

(lldb) po state as? SyncState.Loading
nil
let state = repo.currentSyncState()
…

(lldb) po state
Active(syncNumber=syncNumber 123)

(lldb) po state is SyncState
true

(lldb) po state is SyncState.Active
false

(lldb) po type(of: state)
SyncStateActive

(lldb) po state as? SyncState.Active
nil

一个可能的解决方案可能是在每个状态中添加KMM中的其他类型枚举情况,但这仍然不允许我处理相应状态的相关值。

有人有类似的问题吗?为他们找到了可能的解决方案? 我感谢所有小建议。

我使用的是Kotlin 1.6.10和Xcode 13.2,带有Swift 5.5.2。

Within my KMM library I use sealed interfaces/classes to represent certain states/errors.
I decided to use sealed interfaces/classes because these states must have different associated objects.

In the Android code, this also works as expected without any problems.

But in the iOS part, I'm not able to detect the specific state because the cast is not possible.

The error is independent of whether it is a sealed interface or a sealed class, here as an example:

sealed class SyncState() {
    object Loading : SyncState()
    data class Active(val syncNumber: String) : SyncState()
    data class Error(val throwable: Throwable) : SyncState()
}

In the repository within the KMM library, a corresponding SyncState is now returned depending on the state.

fun currentSyncState(): SyncState {
    if … {
        return SyncState.Error(Throwable("…"))
    } else if … {
        return SyncState.Active("…")
    } else {
        return SyncState.Loading
    }
}

In iOS, I can also call up this function without any problems.
The only problem is that I can't tell which state it is from the object that is returned, because the casting doesn't work at any point.

let state = repo.currentSyncState()
…

(lldb) po state
SyncState.Loading@2fe538

(lldb) po state is SyncState
true

(lldb) po state is SyncState.Loading
false

(lldb) po type(of: state)
SyncStateLoading

(lldb) po state as? SyncState.Loading
nil
let state = repo.currentSyncState()
…

(lldb) po state
Active(syncNumber=syncNumber 123)

(lldb) po state is SyncState
true

(lldb) po state is SyncState.Active
false

(lldb) po type(of: state)
SyncStateActive

(lldb) po state as? SyncState.Active
nil

A possible solution might be to add an additional Type enum case in KMM for every State, but this still does not allow me to process the associated value of the corresponding state.

Has anyone had similar problems & found a possible solution for them?
I am grateful for every little advice.

I'm using Kotlin 1.6.10 and Xcode 13.2 with Swift 5.5.2.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

三月梨花 2025-01-27 03:26:49

我在

I used a library at https://github.com/icerockdev/moko-kswift for the same problem. It gives you autogenerated swift enums with constructors that take your Obj C type generated from the sealed class in Kotlin, and also mapping back to the Obj C type.

醉南桥 2025-01-27 03:26:49

我建议不要使用从 Swift 生成的密封类。您不会从中得到任何有用的东西,因为它很尴尬并且没有详尽的 when 语句。使用在获得密封类时执行的回调要容易得多。这里有几种方法:

互斥回调

sealed class SyncState() {
    object Loading : SyncState()
    data class Active(val syncNumber: String) : SyncState()
    data class Error(val throwable: Throwable) : SyncState()
}

...

class NativeViewModel (
    onLoading: () -> Unit,
    onActive: (String) -> Unit,
    onError: (Throwable) -> Unit
)

在 Swift 中:

let mainViewModel = NativeViewModel(
    onLoading: { ... },
    onActive: { ... },
    onError: { ... }
)

针对所有情况进行 1 个回调

或者,您可以将所有情况包含在具有可为 null 属性的数据类 上的 1 个回调中:

data class SyncState() {
    val loading: Boolean?,
    val active: String?,
    val error: Throwable?
}

...

class NativeViewModel (
    onSyncState: (SyncState) -> Unit
)

在 Swift 中:

let mainViewModel = NativeViewModel(
    onSyncState: { ... }
)

I'd recommend not using your generated sealed classes from Swift. You don't get anything helpful from it, because it's awkward and there is no exhaustive when statement. It's much easier to use a callback that should execute when you get that sealed class. Here are a couple ways:

Mutually exclusive Callbacks

sealed class SyncState() {
    object Loading : SyncState()
    data class Active(val syncNumber: String) : SyncState()
    data class Error(val throwable: Throwable) : SyncState()
}

...

class NativeViewModel (
    onLoading: () -> Unit,
    onActive: (String) -> Unit,
    onError: (Throwable) -> Unit
)

And in Swift:

let mainViewModel = NativeViewModel(
    onLoading: { ... },
    onActive: { ... },
    onError: { ... }
)

1 Callback for all cases

Alternatively, you could encompass all cases in 1 callback on a data class with nullable properties:

data class SyncState() {
    val loading: Boolean?,
    val active: String?,
    val error: Throwable?
}

...

class NativeViewModel (
    onSyncState: (SyncState) -> Unit
)

And in Swift:

let mainViewModel = NativeViewModel(
    onSyncState: { ... }
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文