How to unsubscribe?

If I have something like this:

  func foo() -> Observable<Foo> {
    return Observable.create { observer in
      // ...
    }
  }

  func bar() {
    foo().observeOn(MainScheduler.instance)
      .subscribeNext {
        // ...
      }
      .addDisposableTo(disposeBag)
  }

If I want to unsubscribe from what was later seen in bar, how would I do it?

Update

I know that I can call dispose, but according to the RxSwift Docs :

Note that you usually do not want to manually call dispose; this is just an educational example. Calling recycling manually is usually a bad code smell.

So, unsubscribejust not implemented? I went through the RxSwift code, and as far as I understand what is happening, it does not look like the Disposableone returned from the subscription methods always has useful functions (other than deleting).

+4
source share
4

Observable, foo disposeBag. . "" disposeBag,

disposeBag = nil

- .

: Observables, , . Observable, , takeUntil .

//given that cancellingObservable sends `next` value when the subscription to `foo` is no longer needed

foo().observeOn(MainScheduler.instance)
  .takeUntil(cancellingObservable)
  .subscribeNext {
    // ...
  }
  .addDisposableTo(disposeBag)
+3

, , .

:

this.myVariable$.pipe(takeUntil(this.ngUnsubscribe)).subscribe(value => {
  // Do the thing you want to do after there is change in myVariable
});

:

ngOnDestroy() {
  this.ngUnsubscribe.next();
  this.ngUnsubscribe.complete();
}

ngOnDestroy, .

+1

More details

  • Xcode Version 11.0 (11A420a), iOS 13, Swift 5
  • RxSwift v 5.0.1

Decision

if you want to unsubscribe from notes you just need to reset disposeBag

// Way 1
private lazy var disposeBag = DisposeBag()

//...
disposeBag = DisposeBag()

// Way 2
private lazy var disposeBag: DisposeBag? = DisposeBag()

//...
disposeBag = nil

Full sample

import UIKit
import RxSwift

class Service {
    private lazy var publishSubject = BehaviorSubject<Int>(value: count)
    private lazy var count = 0
    var counter: Observable<Int>  { publishSubject }
    func unsubscribeAll() { publishSubject.dispose() }
    func increaseCounter() {
        count += 1
        publishSubject.onNext(count)
    }
}

class ViewController: UIViewController {

    private lazy var service = Service()
    private lazy var disposeBag = DisposeBag()
    private weak var navigationBar: UINavigationBar!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupNavigationBar()
        subscribeToObservables()
    }
}

// MARK: Work with subviews

extension ViewController {

    private func setupNavigationBar() {
        let navigationBar = UINavigationBar()
        view.addSubview(navigationBar)
        navigationBar.translatesAutoresizingMaskIntoConstraints = false
        navigationBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        navigationBar.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
        navigationBar.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true

        let navigationItem = UINavigationItem()
        var barButtons = [UIBarButtonItem]()
        barButtons.append(createNavigationItemButton(title: "subscr.", action: #selector(subscribeButtonTapped)))
        barButtons.append(createNavigationItemButton(title: "unsubscr.", action: #selector(unsubscribeButtonTapped)))
        navigationItem.leftBarButtonItems = barButtons
        navigationItem.rightBarButtonItem = createNavigationItemButton(title: "+", action: #selector(increaseCounterNavigationItemButtonTapped))
        navigationBar.items = [navigationItem]
        self.navigationBar = navigationBar
    }

    private func createNavigationItemButton(title: String, action: Selector?) -> UIBarButtonItem {
        return UIBarButtonItem(title: title, style: .plain, target: self, action: action)
    }

}

// MARK: Work with observers

extension ViewController {
    private func subscribeToObservables() {
        service.counter.subscribe { [weak self] value in
            guard   let value = value.element,
                    let navigationItem = self?.navigationBar?.items?.first else { return }
            navigationItem.title = "Counter \(value)"
            print(value)
        }.disposed(by: disposeBag)

    }

    private func unsubscribeFromObservables() { disposeBag = DisposeBag() }
}

// MARK: Button actions

extension ViewController {
    @objc func increaseCounterNavigationItemButtonTapped(_ source: UIBarButtonItem) { service.increaseCounter() }
    @objc func subscribeButtonTapped(_ source: UIBarButtonItem) { subscribeToObservables() }
    @objc func unsubscribeButtonTapped(_ source: UIBarButtonItem) { unsubscribeFromObservables() }
}

Screenshot of sample application

enter image description here

0
source

What I did was create another DisposeBag

var tempBag = DisposeBag()

fun bar() {
    foo().subscribe().addDisposable(tempBag)
}

so when you want to get rid, you can just do tempBag = nilwhen you want to release. while you still have others DisposeBagthat save other resources.

-1
source

Source: https://habr.com/ru/post/1654389/


All Articles