Getting Started With RxSwift and RxCocoa

I have a problem that xcode not autocomplete rxswift’s components, xcode just autocomplete when i run your project.
I have searched on the internet and tried to fix this problem but i can’t, help me please. I use xcode 8.2.1.
Thanks

Yeah, I’ve had this issue on occasion with any number of Swift projects. The only even halfway reliable thing I’ve found is to clear out my Derived Data folder (~/Library/Developer/Xcode/DerivedData), then go have a very large cup of coffee while you wait for all your indexes to rebuild.

Not really a great solution, but unfortunately this comes down to how Xcode builds the indexes for autocomplete and how often they seem to get either corrupted or otherwise damaged.

Hi! @designatednerd thanks for the article. The Reactive programming is the idea worth sharing :slight_smile:

I have a quick question, since you subscribe inside a viewController and add Disposable into the viewController’s disposeBag don’t you have the retain cycle problem?

Hey, sorry for the slow reply! Excellent question.

So the fun thing about DisposeBag is that it takes care of all the unsubscriptions for you. You can read a bit about this in the RxSwift documentation, but the short answer is that when the DisposeBag itself gets deallocated, it goes through and automatically disposes of all the subscriptions, so that retain cycles are not created.

Hey @designatednerd.
Don’t be sorry :wink: We all are busy these days. Thanks for the answer anyway :slight_smile:

However, I’ve run the code with the profiler and unfortunately there are 2 retain cycles:

Small side note. To check if ChocolatesOfTheWorldViewController has the retain cycle I’ve just add one UIViewController before into navigation stack. I wanted to be able to dismiss the ChocolatesOfTheWorldViewController.

The dispose bag

but the short answer is that when the DisposeBag itself gets deallocated, it goes through and automatically disposes of all the subscriptions, so that retain cycles are not created.

Indeed, all the disposables are deallocated if DisposeBag is deallocated, however in our case the DisposeBag won’t ever be deallocated.

The disposeBag is hold by the UIViewController which is hold by the Observable which has strong reference from the Disposable which is inside the disposeBag. Aghh that loop, it is easy to get lost :smiley:


UIViewController ------> disposeBag ------> Disposable ------> Observable ------> the UIViewController


To avoid the retain cycle in ChocolatesOfTheWorldViewController and in BillingInfoViewController you would have to add [weak self]/[unowned self] in each Observable’s closure which calls self

I hope I’ve helped :wink:

Hm. Even Rx’s example code doesn’t reference self as unowned or weak in places like this example of a View Controller from a storyboard which loads Github Repositories. It’s a little weird because it’s subclassing a base VC which handles setup of the disposeBag, but as far as I can tell there’s not anything THAT different from the setup of the sample app here.

Unfortunately I think why it’s fine in that sample app and doesn’t work here is beyond the scope of my personal experience with Rx. I know @icanzilb has a lot more experience than I do working with Rx day-to-day. Marin, do you know what the deal is with this?

haha I’ve found why :D. Official Examples also have the retain cycle in GitHubSearchRepositoriesViewController :frowning:.
What’s good, this is the only one UIViewController which leaks :relieved:

Zrzut ekranu 2017-02-13 07.16.23

Let’s wait what @icanzilb has to say :wink:

@designatednerd oh yes - if you don’t specify unowned or weak view controller is definitely going to be retained. The dispose bag itself takes care to memory manage the subscriptions, but if you retain the view controller itself - that’s on you :smile:

Rules of thumb I’ve discussed with others are - use unowned if you can guarantee the subscription will be disposed before self, use nothing (i.e. no unowned and no weak) if this is the root view controller that is never going to be released anyway, use weak in all other cases.

Regarding the RxSwift example app - my guess is few of these were one view controller examples before they were merged into one big showcase and that’s why the code originally didn’t have [weak self], and this is a great example why [self weak] is simply the best option to go with :slight_smile:

Awesome, thank you for the clarification @icanzilb!

And @theadamborek maybe you can open a PR on the example code to fix that :nerd:

How to test that code with RxTest? I mean the Observable with Array

1 Like

Excellent question! Much as I am a testing advocate, I haven’t had much time to dive into testing with Rx. However, there is a whole RxTest folder on the RxSwift repo with its own podspec.

@icanzilb has a couple posts on this on his site discussing how to use it:

Those should be good places to start looking into how to test this stuff if you want to unit test it.

@destroplayer to test your Observables you can use additional libraries like RxTest or RxBlocking. However, remember that you need to write applications with the architecture which increases the testability. MVVM seems to be a common choice in Rx based architectures.

MVVM

About MVVM I can recommend

Testing

About testing itself you’re welcome to visit my blog ;). I’ve written one post only about unit-testing in RxSwift

I can also recommend 5th part of RxSwift Primer Series

Enjoy reading :books::muscle:

RxSwift and RxCocoa also have an additional tool to help deal with ARC and memory management: the DisposeBag. This is a virtual “bag” of Observer objects which are disposed of when their parent object is deallocated.

So to be a good ARC citizen, remember to add any Observable objects to the DisposeBag when you set them up. That way, they’ll be cleaned up nicely for you.

In the first paragraph it sounds like Observer objects go into the DisposeBag.

In the second paragraph it sounds like Observable objects go into the DisposeBag.

Please explain.

Yeah, that’s not super clear. Let me take a stab at more detail as I understand it (although I will say that @icanzilb is probably going to be able to give a way better answer than me).

If you look at the code for ObservableType, the root protocol behind Observable, you’ll see that every Observable returns a Disposable subscription when subscribe is called, representing the relationship between the Observable and the Observer.

These Disposable subscriptions are what go into the DisposeBag. The bag makes it easy to call dispose() on all the subscriptions in it, such as when a view controller gets to deinit. When dispose() is called on an individual subscription, that subscription is terminated and anything which was subscribed to (ie, an Observable) or listening to the subscription (ie, an Observer) has its retain count decremented automatically by ARC.

So as I understand it, it’s neither an Observable nor Observer object which is getting placed in the DisposeBag. However, when the bag is emptied, both Observables and Observers get cleaned up.

So basically, both paragraphs are wrong. :stuck_out_tongue:

Again, @icanzilb, please feel free to correct whatever I’ve got wrong here.

That sounds accurate, bags dispose subscriptions. When an observable’s subscriptions go down to zero - it’s being released (so to say) 
 often times you don’t even need a dispose bag - e.g. when the observable completes all its subscriptions are being diposed but I’d always use one anyway to have a way to bind the subscriptions to another object’s lifetime (for example a view controller)

Thanks for the extra explanation.

This tutorial is more than six months old so questions regarding it are no longer supported for the moment. We will update it as soon as possible. Thank you! :]