0

I am new to RxSwift and here I would like to ask a question about where should the DisposeBag be.

My case is, I have retrieve a list of items being displayed in a tableview, and each of them will have its own flag to indicate if it is selected.

So I am not just binding the result list to the tableview. I need to have some logic which editing the list on local while user navigate via the tableview.

I have created an instance Variable([Item]) in the ViewModel but if I place the logic in the ViewModel a DisposeBag is needed.

After having some googling, most of the examples of MVVM+RxSwift which have instances of Variable place the DisposeBag in ViewModel but some say it should only be placed in ViewController. Is that true? How can I listen the Observable in ViewModel so that my business logic can be placed in ViewModel?

wsli
  • 21
  • 1
  • 1

3 Answers3

7

A DisposeBag more often than not should not be placed in a ViewModel unless there's a good reason.

In general a DisposeBag is meant to tie subscriptions to their owner. It is usually not the case that the ViewModel creates any subscriptions, but merely provides Observables so a consumer could subscribe to them (for example a ViewController).

That means the ViewController is the one to usually hold the DisposeBag, as its usually the one that uses the subscriptions (and not the ViewModel itself).

Shai Mishali
  • 9,224
  • 4
  • 56
  • 83
  • In my case, API calls take place in the viewModel, so is it ok to use the DisposeBag inside the viewModel? Notice: API calls is also done with Rx. – Ahmed Elgendy Jul 30 '19 at 07:55
  • It doesn't make a lot of sense. Yes, the network request are "declared" in the View Model, but the consumer is whoever subscribes to the stream (the View Controller), so it should hold the DisposeBag. – Shai Mishali Jul 30 '19 at 17:39
1

Yes Disposable bag can be placed in viewModel.Wherever there is observable you create , there is a need to dispose of observable.So it can be taken in viewModels as well.As you are new to Rxswift , I recommend to go through this blog for further clarity of RxSwift: https://medium.com/@arnavgupta180/shift-from-swift-to-rxswift-8dece8af9f4

Arnav
  • 668
  • 6
  • 14
  • Disposability is a general RxSwift concept, but aren't DisposeBags generally tied to subscriptions rather than Observables? It seems to me that the rule is generally that wherever you subscribe to a potentially nonterminating sequence, you need a DisposeBag. So I'd interpret the underlying question here to be "Is it OK for ViewModels to subscribe to sequences, or should they be limited to vending Observables?" – GSnyder May 31 '18 at 19:27
0

You can place Disposable or DisposeBag in ViewModel, it's all up to when you want subscriptions to die. It's a good practice to keep them all in one place, as for ex. ViewController. Where will be much easier to handle subscriptions, as sometimes you don't really need a subscription for business logic, ex. when scroll view scrolls you disable a button. (But still, there are architectures, like RxMVP, where it's the other way around)

In your case, you can combine Observables instead of having a variable in ViewModel. It all depends on your needs, but you can have something like:

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()
    }

}

If you have this items coming from Realm or CoreData, you can use Rx implementations for your database, so it will emit an event every time your entity is modified.