假设我们有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
)是否可以观察整个数组并对元素更改中的单个属性做出反应? 不知道我应该如何实现这一目标。
我对这种情况的处理方式可能是完全错误的。但是我不确定我应该如何以不同的方式在这里工作。
答案 0 :(得分:1)
entity
和isSelected
变量需要是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
可观察性)中的大多数复杂性来自必须将可观察性包装到可观察性内部。最好将其分解一下,或者从InvoiceDataModel内部删除变量。
答案 1 :(得分:0)
首先,请注意,RxCocoa中不推荐使用Variable(改为使用BehaviorRelay)。
一种简单的解决方案是将isSelected
可观察值合并为一个可发射的可观察量。我只是将这些代码片段放在一起,但它应该为您指明正确的方向。
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。 (不要忘记.distinctUntilChanged()
,否则您将看到很多发出的元素。)