【问题标题】:RxSwift observing changes in arrayRxSwift 观察数组的变化
【发布时间】:2018-07-04 16:05:02
【问题描述】:

假设我们有 InvoiceDataModel 数组

private let invoices Variable<[InvoiceDataModel]> = Variable([])

class InvoiceDataModel { 
    let id: Variable<Int>
    var entity: Variable<InvoiceDto>
    var isSelected: Variable<Bool> 
}

点击复选框时,我正在更改 isSelected 的值。 我想要实现的是对 isSelect 更改做出反应:

  • 计算选中项的总量(每个实体有var amount: Double
  • 检测是否选择了集合中的所有项目

是否可以观察整个数组并根据元素更改对单个属性做出反应? 不知道我应该如何实现这一目标。

可能我对这个案子的处理是完全错误的。但是我不确定我应该如何以不同的方式在这里操作。

【问题讨论】:

    标签: ios swift rx-swift rx-cocoa


    【解决方案1】:

    entityisSelected 变量需要是 let 而不是 vars。

    这是我想出的解决方案:

    let selectedsAndAmounts = invoices
        .asObservable()
        .flatMapLatest {
            Observable.combineLatest($0.map {
                Observable.combineLatest($0.isSelected.asObservable(), Observable.just($0.amount)) { (isSelected: $0, amount: $1) }
            })
        }
    
    let allSelected = selectedsAndAmounts
        .map { $0.map { $0.isSelected } }
        .map { $0.contains(false) == false }
    
    let amountOfSelected = selectedsAndAmounts
        .map { $0.map { $0.isSelected ? $0.amount : 0 } }
        .map { $0.reduce(0, +) }
    

    这个解决方案(selectedsAndAmounts observable)的大部分复杂性来自于必须在 observables 中解包 observables。如果你能把它分解一下,或者从 InvoiceDataModel 中删除变量会更好。

    【讨论】:

      【解决方案2】:

      首先,请注意在 RxCocoa 中不推荐使用 Variable(改用 BehaviorRelay)。

      一个简单的解决方案是将isSelected 可观察对象组合成一个单独的、发射量的可观察对象。我只是把这个 sn-p 放在一起,但它应该会为你指明正确的方向。

      invoices
          // whenever the list changes, subscribe to the combined observable (and dispose of any previous subscriptions)
          .flatMapLatest { list in
              // merge all isSelected observables together
              return Observable.merge(list.map { $0.isSelected })
          }
          // when an element is emitted, that means some `isSelected` observable has changed its value
          // get the latest invoices array 
          .withLatestFrom(invoices)
          // convert it from a InvoiceDataModel array to a summed amount of all elements
          .map { $0.reduce(0) { $0 + $1.amount } }
          // log all events passing through
          .debug()
          .subscribe()
          .disposed(by: yourDisposeBag)
      

      您可以使用类似的方法订阅一个 Observable,如果所有项目都被选中,则该 Observable 会发出。 (不要忘记.distinctUntilChanged(),否则你会看到很多发射的元素。)

      【讨论】:

        猜你喜欢
        • 2016-06-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多