在 iOS 上,对于 MVVM 中的 DisposeBag,可以放在 ViewModel 中吗?

Posted

技术标签:

【中文标题】在 iOS 上,对于 MVVM 中的 DisposeBag,可以放在 ViewModel 中吗?【英文标题】:On iOS, for the DisposeBag in MVVM, can it be placed in ViewModel? 【发布时间】:2018-05-17 02:59:10 【问题描述】:

我是 RxSwift 的新手,在这里我想问一个关于 DisposeBag 应该放在哪里的问题。

我的情况是,我检索了一个在 tableview 中显示的项目列表,每个项目都有自己的标志来指示它是否被选中。

所以我不只是将结果列表绑定到 tableview。当用户通过 tableview 导航时,我需要一些逻辑来编辑本地列表。

我在ViewModel 中创建了一个实例Variable([Item]),但如果我将逻辑放在ViewModel 中,则需要DisposeBag

在谷歌搜索后,大多数具有Variable 实例的 MVVM+RxSwift 示例将DisposeBag 放在ViewModel 中,但有人说它应该只放在ViewController 中。真的吗?如何在ViewModel 中监听Observable,以便我的业务逻辑可以放在ViewModel 中?

【问题讨论】:

【参考方案1】:

DisposeBag 通常不应该放置在 ViewModel 中,除非有充分的理由。

一般来说,DisposeBag 用于将订阅与其所有者联系起来。通常情况下,ViewModel 不会创建任何订阅,而只是提供 Observables,以便消费者可以订阅它们(例如 ViewController)。

这意味着 ViewController 通常持有DisposeBag,因为它通常使用订阅(而不是 ViewModel 本身)。

【讨论】:

在我的例子中,API 调用发生在 viewModel 中,那么在 viewModel 中使用 DisposeBag 可以吗?注意:API 调用也是通过 Rx 完成的。 这没有多大意义。是的,网络请求是在视图模型中“声明”的,但消费者是订阅流的人(视图控制器),所以它应该持有 DisposeBag。【参考方案2】:

Yes Disposable bag 可以放在 viewModel 里面。哪里有你创建的 observable 就需要 dispose observable 。所以也可以放在 viewModels 里面。由于你是 Rxswift 新手,建议你去看看这个博客进一步清楚 RxSwift: https://medium.com/@arnavgupta180/shift-from-swift-to-rxswift-8dece8af9f4

【讨论】:

Disposability 是一个通用的 RxSwift 概念,但 DisposeBags 通常不是与订阅相关联而不是 Observables 吗?在我看来,规则通常是,无论您订阅一个潜在的非终止序列,您都需要一个 DisposeBag。所以我将这里的基本问题解释为“ViewModel 订阅序列是否可以,还是应该仅限于出售 Observables?”【参考方案3】:

您可以在 ViewModel 中放置 DisposableDisposeBag,这完全取决于您希望订阅何时终止。将它们全部放在一个地方是一种很好的做法,例如前。视图控制器。哪里会更容易处理订阅,因为有时你真的不需要订阅业务逻辑,例如。当滚动视图滚动时,您禁用一个按钮。 (但仍有一些架构,比如 RxMVP,情况正好相反)

在您的情况下,您可以组合 Observables 而不是在 ViewModel 中使用变量。这完全取决于您的需求,但您可以有类似的东西:

class ViewModel 

    var activeItems: Observable<[Item]> 
        return Observable.combineLatest(retrieveData(), itemEdited().startWith(nil))  (allItems, editedItem) in
            // TODO: check if edited item should be in list
        
    

    private func retrieveData() -> Observable<[Item]> 
        return .empty()
    

    private func itemEdited() -> Observable<Item?> 
        return .empty()
    


如果您有这些来自 Realm 或 CoreData 的项目,您可以为您的数据库使用 Rx 实现,因此每次修改您的实体时它都会发出一个事件。

【讨论】:

以上是关于在 iOS 上,对于 MVVM 中的 DisposeBag,可以放在 ViewModel 中吗?的主要内容,如果未能解决你的问题,请参考以下文章

iOS MVVM+RAC

iOS 开发中的 MVVM 模式——实用进阶篇(整理)

iOS中的MVVM示例/示例实现[关闭]

iOS架构补完计划--浅谈架构模式(MVC/MVVM)

浅谈iOS中的MVC MVP MVVM

IOS的MVC和MVVM模式简明介绍