斯威夫特 为一个属性组合两个处理程序



我有一个使用UITableViewDiffableDataSourceUIViewController。我有一个这个控制器的视图模型,看起来像:

class ListViewModel {
@Published private(set) var items: [Item] = []

func load(params: [String: Any] = [:]) {
WebRepo().index(params: params, completion: { [weak self] (items, error) in
self?.items = items
})
}

func deleteFirst() {
self.items.remove(object: self.items.first)
}
}

在我的VC中,我有一个绑定,如下所示:

self.viewModel.$items.sink { [weak self] (scenes) in
self?.update(items: items, animated: false)
}.store(in: &self.subscriptions)

所以,当我调用视图模型的load方法时 - 我想做self?.update(items: items, animated: false),但是当我调用deleteFirst时 - 我想self?.update(items: items, animated: true).

我对反应式和组合很陌生,所以不确定处理这个问题的正确方法是什么。 我可以isReset属性添加到我的视图模型中load并将方法更改为以下内容:

func load(params: [String: Any] = [:]) {
WebRepo().index(params: params, completion: { [weak self] (items, error) in
self?.isReset = true
self?.items = items
self?.isReset = false
})
}

在里面sink只是检查此属性,但它对我来说不是一个合适的方式。

这是一种思考方式。不要发布items,而是使用输出类型为元组的直通主体,([Items], Bool)。视图控制器订阅该主题。

现在,当您调用load时,使用(items, false)调用直通主体的send,但是当您调用delete时,请使用(items, true)调用直通主体的send

换句话说,让您的发布者发布下游需要的所有信息,以便知道该怎么做。

您可能会认为这种方法相当极端,但是将内容聚集到一个元组中以便将多条信息传递到管道中是正常行为。实际上,这是调用具有两个参数的方法的反应式等价物。


另一种可能性可能是下游考虑该发布商发布了多少次。例如,如果 ViewModel 只调用load一次,这将起作用。如果是这种情况,下游管道将能够使用运算符(例如scanfirst或其他)来区分流水线中的第一个值(这意味着我们不想进行动画处理)和任何后续值(我们确实想要进行动画处理)。


另一种思考方式是将责任完全放在构建快照的人身上。如果可比较数据源的快照为空,则它没有数据,我们不想进行动画处理。如果不为空,我们确实想要动画。同样,这只有在适用于您的目的时才有效。

相关内容

  • 没有找到相关文章

最新更新