簡體   English   中英

KMM - 在 swift 中鑄造密封類/接口是不可能的

[英]KMM - Casting a sealed class/interface in swift not possible

在我的 KMM 庫中,我使用密封的接口/類來表示某些狀態/錯誤。 我決定使用密封接口/類,因為這些狀態必須有不同的關聯對象。

在 Android 代碼中,這也按預期工作,沒有任何問題。

但在 iOS 部分,我無法檢測到具體的 state,因為無法進行轉換。

報錯與是密封接口還是密封class無關,這里舉例:

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

在 KMM 庫中的存儲庫中,現在根據 state 返回相應的 SyncState。

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

iOS,我也可以毫無問題的撥打這個function。 唯一的問題是我無法從返回的 object 中分辨出它是哪個 state,因為轉換在任何時候都不起作用。

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 中為每個 State 添加一個額外的 Type enum case,但這仍然不允許我處理相應 state 的關聯值。

有沒有人遇到過類似的問題並找到了可能的解決方案? 我很感激每一個小建議。

我正在使用 Kotlin 1.6.10 和 Xcode 13.2 和 Swift 5.5.2。

我在https://github.com/icerockdev/moko-kswift使用了一個庫來解決同樣的問題。 它為您提供了自動生成的 swift 枚舉,其構造函數采用從 Kotlin 中的密封 class 生成的 Obj C 類型,並且還映射回 Obj C 類型。

我建議不要使用您從 Swift 生成的密封類。您不會從中得到任何幫助,因為它很尷尬並且沒有詳盡的when語句。 當你得到密封的 class 時,使用應該執行的回調要容易得多。這里有幾種方法:

互斥回調

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 所有案例的回調

或者,您可以將所有情況包含在具有可為空屬性的data class的 1 個回調中:

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

...

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

在 Swift 中:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM