gpt4 book ai didi

swift - LSP 和 SwiftUI

转载 作者:搜寻专家 更新时间:2023-11-01 06:25:01 27 4
gpt4 key购买 nike

为了使我的代码可测试,我正在尝试遵守 Liskov's substitution principle让我的 SwiftUI View 依赖于协议(protocol)而不是具体类型。这使我可以轻松地交换实现,并允许我轻松地构建用于测试的模拟。这是我正在尝试做的一个例子:

protocol DashboardViewModel: ObservableObject {

var orders: [Order] { get }
}

我的 DashboardViewModel 需要将更改传达回其依赖项,因此我还附加了 ObservableObject 作为传递要求。

这似乎是个问题。如果您有关联的类型要求,您不能实现 LSP。这是我从我的 SwiftUI View 类中得到的错误,该错误取决于我的 View 模型:

struct DashboardView: View {
@ObservedObject var viewModel: DashboardViewModel
}

Protocol 'DatastoreProtocol' can only be used as a generic constraint because it has Self or associated type requirements

我最终这样做了:

protocol DashboardViewModel {

var orders: [Order] { get }
var objectWillChange: AnyPublisher<Void, Never> { get }
}

这也需要家属做额外的工作来观察状态变化。这剥夺了使用属性包装器的便利 - 主要是依赖项使用 @ObservedObject 观察状态变化的能力。使用这种替代方法会导致我们编写如下代码:

struct DashboardView: View {
let viewModel: DashboardViewModel

var viewModelSubscriber: AnyCancellable!

// MARK: - Used only to force a re-render of this view
@State private var reload = false

init(viewModel: DashboardViewModel) {
self.viewModel = viewModel
viewModelSubscriber = viewModel.objectWillChange.sink { _ in
self.reload.toggle()
}
}
}

这看起来有点令人反感:

  1. 创建了一个仅用于强制更新 View 的 @State 变量,因为我们无法利用 SwiftUI 属性包装器来观察状态变化

  2. 创建了一个 AnyCancellable! 变量来保存对 View 模型中 objectWillChange 的订阅。这是检测 DashboardViewModel

  3. 的状态变化所必需的
  4. 在初始化器中添加了订阅调用,它只切换 @State 变量以强制从 View 模型中检索新数据

我觉得应该有更好的方法来处理这个问题。寻求帮助!

最佳答案

解决这个问题的一种方法是使您的 View 通用:

protocol DashboardViewModel: ObservableObject {
var orders: [Order] { get }
}

struct DashboardView<Model: DashboardViewModel>: View {
@ObservedObject var viewModel: Model
}

关于swift - LSP 和 SwiftUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57579380/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com