首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LSP和SwiftUI

LSP和SwiftUI
EN

Stack Overflow用户
提问于 2019-08-20 18:10:25
回答 1查看 184关注 0票数 1

为了使我的代码具有可测试性,我试图通过让我的Liskov代换原理视图依赖于协议而不是具体类型来坚持SwiftUI。这使我可以轻松地交换实现,并且可以轻松地构建用于测试的模拟。下面是我要做的事情的一个例子:

代码语言:javascript
复制
protocol DashboardViewModel: ObservableObject {

  var orders: [Order] { get }
}

我的DashboardViewModel需要将更改传递回它的依赖方,所以我也附加了ObservableObject作为传递的需求。

这似乎是个问题。如果您有关联的类型需求,则无法实现LSP。下面是我从SwiftUI视图类中获得的错误,它依赖于我的视图模型:

代码语言:javascript
复制
struct DashboardView: View {
  @ObservedObject var viewModel: DashboardViewModel
}

协议'DatastoreProtocol‘只能用作泛型约束,因为它具有自或关联的类型要求

我最终还是这么做了:

代码语言:javascript
复制
protocol DashboardViewModel {

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

这还要求受抚养人做额外的工作来观察状态更改。这就消除了使用属性包装器的方便性--主要是受抚养人使用@ObservedObject观察状态更改的能力。使用此选项将导致我们编写如下代码:

代码语言:javascript
复制
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. 创建了一个仅用于强制更新视图的@State变量,因为我们不能利用SwiftUI属性包装来观察状态更改。
  2. 创建一个AnyCancellable!变量,以保存视图模型中对objectWillChange的订阅。这是从DashboardViewModel检测状态更改所必需的。
  3. 在初始化器中添加了订阅调用,它仅切换@State变量以强制从视图模型检索新数据。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-08-20 18:18:54

解决这一问题的一种方法是使视图具有通用性:

代码语言:javascript
复制
protocol DashboardViewModel: ObservableObject {
    var orders: [Order] { get }
}

struct DashboardView<Model: DashboardViewModel>: View {
    @ObservedObject var viewModel: Model
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57579380

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档