Hey, question for y'all about how to deal with subscriptions and the lifecycle of a UIViewController. I think I know the answer, but I want to validate my thinking, and I haven't seen a good explanation of this.
So let's say I have my ListOfFoosViewController, which in addition to a list of Foos also includes a live update of the phone's current position, battery strength, the most recent stock price of AAPL, and a couple of other things. All those are based on subscriptions to observables, with the disposables added to a DisposeBag like a good RxSwifter.
Now, the user taps on one of those Foos and we segue to the FooDetailViewController. ListOfFoosViewController slides off and the new VC slides on.
It seems like all those subscriptions will still be pumping as long as the ListOfFoosViewController stays in memory and whatnot. Some of those subscriptions may be expensive, so this is less than ideal.
I _think_ the right thing to do is to gather all the live subscriptions in either a DisposeBag or a CompositeDisposable and dispose of them when ListOfFoosViewController slides offscreen, probably in an implementation of viewWillDisappear:. And then rebuild all those subscriptions in viewWillAppear:, which for simplicity's sake then becomes a better place to build the bindings in the first place than viewDidLoad:, at least for subscriptions we want to have mirror whether the VC is on screen or not.
Does this make sense? If there's already a good explanation I'd love a pointer, and if there's not, I think by opening this I'm signing up to write one if there isn't. :)
class FooDetailViewController: UIViewController {
var disposeBag: DisposeBag!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.disposeBag = DisposeBag()
someObservable
.subscribeNext { value in
// Do something
}
.addDisposableTo(self.disposeBag)
someOtherObservable
.subscribeNext { value in
// Do something
}
.addDisposableTo(self.disposeBag)
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
self.disposeBag = nil
}
Just like you said. I've been using this for quite a while and it has always worked well.
A nice side effect of this method is if you subscribe to the same observable in the next view and that observable shares its underlying observable you keep that same subscription.
@thanegill Perfect, thanks for the validation! I don't quite follow your side effect but it's still good to validate our pattern. :)
@kzaher my offer to add docs stands.
Hi @dpassage ,
missed your comment.
I think that it would be great if you could create blog posts or something like that.
We try to extract everything not vital from this repository (including docs) because we want to have least possible amount of content here :)
Hope that makes sense.
Closing this one.
That sounds promising.
Another question is how can I get the updates while the view controller was disappearing.
Let's say someObservable has had a new value before re-subscription after disappearing. How do I get that when subscribing again?
I know I can use BehaviourSubject but it's not perfect because I need to get update only if there has been one while it seems like always sending the last value.
I think this approach might break a "Delegate" style signal flow if there is a signal between the FooDetailViewController and ListOfFoosViewController, other than that I think this is a great method of disposing expensive work on the disappearing viewController
Most helpful comment
Just like you said. I've been using this for quite a while and it has always worked well.
A nice side effect of this method is if you subscribe to the same observable in the next view and that observable shares its underlying observable you keep that same subscription.