【问题标题】:Observe change in Published property within an array using Combine使用 Combine 观察数组中 Published 属性的变化
【发布时间】:2020-08-17 07:07:20
【问题描述】:

我有一个现有代码,其中 UITableView 使用委托监视其数据源的更改(以便对点击节标题以展开/折叠行做出反应)。

我想使用 Combine 来代替订阅者并监视对数据源的更改。数据源是一个数组,我想在其中监视对类属性的更改。所以:

public class SectionViewModel: ObservableObject, Identifiable, Equatable {
  public static func == (lhs: SectionViewModel, rhs: SectionViewModel) -> Bool {
    return lhs.id == rhs.id
  }

  public var id: Int = 0

  @Published var isExpanded = true

  public init(id: Int, isExpanded: Bool = true) {
    self.id = id
    self.isExpanded = isExpanded
  }
}

// Data source
var models = [
  SectionViewModel(id: 0, isExpanded: true),
  SectionViewModel(id: 1, isExpanded: true),
  SectionViewModel(id: 2, isExpanded: true),
  SectionViewModel(id: 3, isExpanded: true),
]

模型被传递给每个UITableViewHeaderFooterViews,然后在点击时切换isExpanded。我是否需要创建和维护一个订阅者数组(通过sink)并在数组内容更改时取消它们?以下是正确的方法吗?

let allModelSubscription = models.map { model in
  model.$isExpanded.sink { (expanded) in
    print("Model changed: \(model.id)")
  }
}

这可行,但是当视图控制器第一次加载时,我会被发布的更改轰炸,这是可以理解的。我怎样才能避免这种情况?

【问题讨论】:

  • 我不确定最佳实践是什么 - 想确保它是如何完成的,并且不确定如何避免最初发布的更改到达下游。抱歉,我使用 Combine 的第一天,实际上是我尝试使用它的第一个小时。
  • 我想观察模型类内部模型和 Published 属性的变化,以便在扩展状态发生变化以及模型本身发生变化时做出反应。可以说,我可以使用 iOS 13 中的 Diffable 数据源——接下来需要研究一下。但是现在我希望能够绑定/响应节标题更改的已发布属性。不确定我是否理解可变数组是一个糟糕的模型选择。
  • 很公平,虽然我应该补充一下,这更像是一个元模型表示,以便该部分能够使用,同时为了方便起见,使用它来表示其状态。我可能应该将其他属性设为不可变,但我想保留 isExpanded 一个已发布的可变属性,以便观察状态变化。这是个坏主意吗?
  • 似乎@Published 属性只能定义为class 的一部分 - 所以按照惯例,模型需要是可变的。这不是视图控制器和视图之间的绑定方式吗?

标签: swift combine


【解决方案1】:

不清楚你所有的依赖,但是试试下面的

@Published var isExpanded: Bool   // << only declaration

public init(id: Int, isExpanded: Bool = true) {
   self.id = id
   _isExpanded = Published(initialValue: isExpanded) // << explicit
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 2017-05-07
    • 2013-10-24
    • 2016-06-16
    • 1970-01-01
    相关资源
    最近更新 更多