1

对不起,我的英语不好 :(

我想用 KMM 创建应用程序,并最大化共享代码。只有我想写两次的是 UI 和导航。所以我在共享代码中创建 ViewModel。

open class ViewModel<T>(initialState: T) where T : ViewState {

    private val _state = MutableStateFlow(initialState)

    val currentState: T
        get() = stateFlow.value

    val stateFlow: StateFlow<T> = _state

    fun updateState(
        context: CoroutineContext = EmptyCoroutineContext,
        mapping: (currentState: T) -> T
    ) { GlobalScope.launch(context) { _state.emit(mapping(_state.value)) } }
}

ViewState 就在哪里

interface ViewState

用于在密封类中实现,描述当前视图状态。当它发生变化时,用户界面会收到变化和更新。状态看起来像(我发现的第一个免费公共 API 返回随机狗图像):

sealed class DogImageViewState : ViewState {
    object Loading : DogImageViewState()
    data class Content(val image: String) : DogImageViewState()
}

好的

所以我创建了具体的 ViewModel 来在 iOS 和 android 之间共享逻辑

class DogImageViewModel(initialState: DogImageViewState) : ViewModel<DogImageViewState>(initialState) {

    private val interactor : GetDogImageUrlInteractor by dogDi.instance()

    init {
        getImage()
    }

    fun reload() {
        updateState { DogImageViewState.Loading }
        getImage()
    }

    private fun getImage() {
        GlobalScope.launch(ioDispatcher) {
            val image = interactor.getImageUrl()
            updateState { (it as? Content)?.copy(image = image) ?: Content(image = image) }
        }
    }
}

简单,尼特?Viewmodel 使用 Loading 进行初始化,并立即开始图像加载。图像加载后进入新状态。在刷新操作上完全相同

在Android中使用很简单,jetpack compose 可以collectAsStateStateFlow,没有什么可做的,只用state来描述一个ui

问题出在 iOS

我们必须为 iOS“桥接”可观察模型。iOS 有ObservableObject机制,我已经扩展了它

class ObservableViewModel<T : ViewState>: ObservableObject {

    @Published var state : T
    
    init(viewModel: ViewModel<T>) {
        self.state = viewModel.currentState
        viewModel.onChange { newState in
            self.state = newState as! T
        }
    }
}

看起来不错。ViewState 的通用类...现在我可以将它与 SwiftUI 一起使用!不好了...

当我尝试ObservableViewModel在代码中使用时,我收到一个错误

    @StateObject var vm = ObservableViewModel<DogImageViewState>(viewModel: DogImageViewModel(initialState: DogImageViewState.Loading()))

类型“DogImageViewState”不符合协议“ViewState”

但它完全符合!

当我跳到定义时,DogImageViewState我会看到下一个

__attribute__((swift_name("DogImageViewState")))
@interface DogDogImageViewState : DogBase <DogSharedViewState>
@end;

看起来完全不符合。什么是Base<ViewState>(DogBase 因为 Dog 功能构建在单独的框架中dog,而 DogSharedViewState 因为 ViewState 中声明shared)?为什么不只是ViewState

如何解释 swift 和 DogSharedViewState 完全一样?

4

0 回答 0