我有一个呈现“节点”列表的VM。每个节点都有一个isCompleted
和isRead
属性。它们呈现在表格视图中,每个单元格都有用于切换这些属性的按钮。
在页面加载时,我从服务器获取列表。现在,我只想更新那些节点。在我的VM中,我尝试了20多种方法,涉及各种操作员,策略,方法等。但是每次尝试都始终存在相同的问题。
我知道这实际上只是在更新某些内容,或者是View-> ViewModel通信。尽管如此,我还是花了令人尴尬的时间花了很多时间来模拟这个模型。因此,我必须缺少RxSwift,MVVM的一些非常基本的方面以及如何为突变建模。
这是我最近的尝试。
let updates = Observable<(NodeIdentifier, AttribUpdate)?>.merge([
toggleMarkReadSubject.map { ($0, AttribUpdate.isRead) },
toggleFavoriteSubject.map { ($0, AttribUpdate.isFavorited) }
]).startWith(nil)
nodes = Observable.combineLatest(dataFromService, updates, resultSelector: { (nodes, update) in
guard let update = update else { return nodes }
switch update.1 {
case .isFavorited:
return nodes.withFavoritedToggled(atId: update.0)
case .isRead:
return nodes.withMarkReadToggled(atId: update.0)
}
}).debug("new nodes", trimOutput: false)
我有一些主题通过nodeIdentifier和update操作(将枚举与每种更新类型的大小写一起使用)将切换事件映射到元组
nodes
是驱动表格视图的主要输出。我combineLatest
了nodesFromService
(服务/ api中的原始节点)。
现在,我得到[Node]
事件,其中切换属性如下所示:[false, true, true, true, true]
。因此它总是从false -> true
开始,因为combineLatest
总是从nodesFromService
获取初始节点数组。
这就是让我发疯的原因。无论我采用哪种方式对其进行切片,这都是周期性的依赖。我真正需要的是将updates
(切换事件)与"final nodes"
流(实际上记住更新的流)组合在一起。但是,如果我什至能够做到这一点,我就会遇到递归的情况。因为updates
首先产生了"final nodes"
流!我感到完全迷失了。非常感谢您的帮助。
答案 0 :(得分:1)
我可以在这里找到两个选择。
由于您不会在节点的当前状态不存储任何位置,因此可以将主题添加到ViewModel中。在这种情况下,您可以保存节点的先前状态。
let nodesSubject = BehaviorSubject(value: [Node]())
...
updateSubject.map { updates in
guard let nodes = try? nodesSubject.value() else { return [] }
// Filter
}.subscribe(nodesSubject) // Save updated nodes back to subject
// update nodes subject on on next (you can do this as side effect instead with do(onNext:))
dataFromService.subscribe(nodesSubject)
在这种情况下,您最终将在ViewModel中获得订阅,这可能不是完美的解决方案。
第二种方法是使用scan运算符。
let nodesStream = Observable.combineLatest(dataFromService, updates).scan(nil) { (previousValues, updates) -> [String] in
var nodes = previousValues ?? updates.0
// Filter
return nodes
}
这种方法可能很难遵循。