首页 > 解决方案 > Swift 为一个属性组合两个处理程序

问题描述

我有一个UIViewControllerwhich using UITableViewDiffableDataSource. 我有这个控制器的视图模型,它看起来像:

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只检查这个属性,但它看起来对我来说不是一个正确的方法。

标签: iosswiftcombine

解决方案


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

现在,当您调用 时load,使用 调用传递主题send(items, false)但是当您调用 时,使用delete调用传递主题。send(items, true)

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

您可能认为这种方法相当极端,但是将事物聚集成一个元组以便将多条信息传递到管道中是正常行为。实际上,这相当于调用带有两个参数的方法。


另一种可能性可能是让下游考虑这个发布者发布了多少次。例如,如果 ViewModelload只调用一次,这将起作用。如果是这种情况,下游管道将能够使用运算符(例如scan,或first,或其他)来区分管道中的第一个值(这意味着我们不想动画)和任何后续值(我们做想要动画)。


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


推荐阅读