Disposing

There is one additional way an observed sequence can terminate. When we are done with a sequence and we want to release all of the resources allocated to compute the upcoming elements, we can call dispose on a subscription.

Here is an example with the interval operator.

let subscription = Observable<Int>.interval(0.3, scheduler: scheduler)
    .subscribe { event in
        print(event)
    }

Thread.sleep(forTimeInterval: 2.0)

subscription.dispose()

This will print:

0
1
2
3
4
5

Note that you usually do not want to manually call dispose; this is only educational example. Calling dispose manually is usually a bad code smell. There are better ways to dispose subscriptions. We can use DisposeBag, the takeUntil operator, or some other mechanism.

So can this code print something after the dispose call executed? The answer is: it depends.

  • If the scheduler is a serial scheduler (ex. MainScheduler) and dispose is called on on the same serial scheduler, the answer is no.

  • Otherwise it is yes.

You can find out more about schedulers here.

You simply have two processes happening in parallel.

  • one is producing elements
  • the other is disposing the subscription

The question "Can something be printed after?" does not even make sense in the case that those processes are on different schedulers.

A few more examples just to be sure (observeOn is explained here).

In case we have something like:

let subscription = Observable<Int>.interval(0.3, scheduler: scheduler)
            .observeOn(MainScheduler.instance)
            .subscribe { event in
                print(event)
            }

// ....

subscription.dispose() // called from main thread

After the dispose call returns, nothing will be printed. That is guaranteed.

Also, in this case:

let subscription = Observable<Int>.interval(0.3, scheduler: scheduler)
            .observeOn(serialScheduler)
            .subscribe { event in
                print(event)
            }

// ...

subscription.dispose() // executing on same `serialScheduler`

After the dispose call returns, nothing will be printed. That is guaranteed.

Dispose Bags

Dispose bags are used to return ARC like behavior to RX.

When a DisposeBag is deallocated, it will call dispose on each of the added disposables.

It does not have a dispose method and therefore does not allow calling explicit dispose on purpose. If immediate cleanup is required, we can just create a new bag.

  self.disposeBag = DisposeBag()

This will clear old references and cause disposal of resources.

If that explicit manual disposal is still wanted, use CompositeDisposable. It has the wanted behavior but once that dispose method is called, it will immediately dispose any newly added disposable.

Take until

Additional way to automatically dispose subscription on dealloc is to use takeUntil operator.

sequence
    .takeUntil(self.rx.deallocated)
    .subscribe {
        print($0)
    }

results matching ""

    No results matching ""