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
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 We all are busy these days. Thanks for the answer anyway
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
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
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
.
Whatâs good, this is the only one UIViewController
which leaks
Letâs wait what @icanzilb has to say
@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
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
Awesome, thank you for the clarification @icanzilb!
And @theadamborek maybe you can open a PR on the example code to fix that
How to test that code with RxTest? I mean the Observable with Array
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:
- Testing your RxSwift code, part 1 // rx_marin<blog>
- Testing your RxSwift code, part 2 // rx_marin<blog>
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
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 Observable
s and Observer
s get cleaned up.
So basically, both paragraphs are wrong.
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! :]