【问题标题】:Swift Combine two handlers for one propertySwift 为一个属性组合两个处理程序
【发布时间】:2020-11-04 18:39:26
【问题描述】:

我有一个UIViewController,它使用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 内部,只需检查此属性,但它看起来对我来说不是正确的方法。

【问题讨论】:

    标签: ios swift combine


    【解决方案1】:

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

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

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

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


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


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

    【讨论】:

    • (与这个问题无关,您还应该将 WebRepo 调用更改为反应式。完成处理程序与组合相反!您应该使用以(延迟)未来开始的管道做网络。)
    • 嗨@matt,谢谢。我正在考虑使用元组,但我认为这是一种解决方法而不是正确的方法:)。我无法使用first 或无法将其传递给数据源,因为用户可以随时通过拉动刷新来重新加载。
    • 顺便说一句,对于元组不需要使用PassthroughSubject,我们可以使用self.items = (newItems, true)
    • 对于任何感兴趣的人,我将 WebRepo 调用更改为响应式,并且也遇到了一些问题,在这里讨论:stackoverflow.com/questions/64697969/…
    猜你喜欢
    • 2019-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    相关资源
    最近更新 更多