Surviving RxSwift

You 100% should be using RxCocoa traits like Driver when you expose values for your view to consume as well as ControlEvent or ControlProperty which you encounter when using properties like UIButton.



This is because those traits are designed specifically to interact with your UI.

They will ensure values are shared and that everything happens on the main thread.

Avoid SubjectsThere are a number of shifts you need to make in how you think about data when learning Rx.

One of the biggest is learning to construct streams such that the values coming out of them are the result of combining and/or transforming the values being sent in.

A simplistic way to think about streams is like a mapping function (A) -> B, or (A, B) -> CQuite often when that shift has not yet been made you will see code that falls back on subjects to bridge the gap.

Subjects are objects in Rx that are both input and output.

They can be subscribed to but also incoming values can be sent to them.

Let’s look at one such example of a view model for performing a search:On its own, this looks quite straightforward.

searchText receives some text and we use that to do our search.

From that, we can define two other streams, one for our list of results and one for a string showing the count.

However, because searchText is both input and output we have accidentally introduced an additional output to our view model.

There is no way for us to prevent something else from subscribing to searchText and executing other code.

If this is something you need to do then you should either:Subscribe directly to the underlying input source (i.


the text field); orCreate another explicit output for this behaviourBy not creating a clear separation between input and output it becomes harder to debug where values may be coming from.

It’s also harder to reason about what the inputs and outputs for your system actually are.

Now let’s see how we might refactor the same view model to remove the use of subjects:The changes here are incredibly subtle.

We have required that the input is passed via the constructor.

This change gives more fine-grained control over what the inputs and outputs are.

We now have a single starting point to search for bugs relating to both text coming in and search results going out.

It’s worth noting that there are, of course, other ways you can go about removing/encapsulating the subjects.

Again, there are exceptions to this one too but I’m not going to go into that here… If you absolutely feel that you need to use subjects, at the very least ensure you are encapsulating them so they are not publicly exposed for any random code to interact with.

I would, however, encourage you to try and avoid them if you can!Limit DisposeBags to View ControllersAnother issue you will see before the shift I mentioned has been made is DisposeBags in places they don’t belong.

A DisposeBag is something that holds subscriptions.

Subscriptions are what you get when you use functions like subscribe, drive or bind.

These subscriptions are also where your apps side-effects are contained.

These subscriptions should be limited to your view controllers.

Other components like view models should not contain subscriptions because they should not contain side-effects.

Interestingly enough, this problem is quite often seen when subjects are also being misused, as mentioned above.

It is common to see subscriptions calling functions like onNext directly.

This is a sign that your stream outputs are not being modelled as transformations of their inputs.

As with the others, there are rare exceptions to this one too.

If, for some reason, a stream does not have an output you may need a single private subscription to ensure the stream is enabled.

However, as with the other exceptions, do your best to avoid this situation.

SummarySo to quickly sum up:Limit Rx to higher level components like view models and view controllers.

Build lower level components without Rx then add Rx wrapper extensions.

Limit yourself to Observable and Driver.

Write your Rx without subjects as much as possible.

DisposeBags really only belong in view controllers.

I would strongly suggest to anyone new to Rx or is feeling overwhelmed by it to simplify your use with these tips.

As you get more comfortable with Rx you will start to get a sense of when and how these tips apply, as well as when they don’t.

.. More details

Leave a Reply