RxSwift 观察数组的变化

Posted

技术标签:

【中文标题】RxSwift 观察数组的变化【英文标题】:RxSwift observing changes in array 【发布时间】: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) 检测是否选择了集合中的所有项目

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

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

【问题讨论】:

【参考方案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(),否则你会看到很多发射的元素。)

【讨论】:

以上是关于RxSwift 观察数组的变化的主要内容,如果未能解决你的问题,请参考以下文章

在 RxCocoa/RxSwift 中,如何观察 BehaviorRelay<[object]> 数组大小发生变化

RxSwift 观察模型的变化并提出请求

如何使用 RxSwift 观察 UITextField 中的文本变化?

RxSwift 可观察数组排序

RxSwift 将可观察对象数组与对象数组结合

如何在 RxSwift 中将值附加到观察到的数组