Top mistakes in RxSwift you want to avoid

Top mistakes in RxSwift you want to avoid

When we learn a new programming language or new frameworks we always do some mistakes. This is how we people learn things.

In this article, I’m want to show you my top 7 mistakes which I did during my Rx trials. I hope I will help you to avoid them πŸ™‚.


#1 – combineLatest vs withLatestFrom

This is the mistake everyone does I think :P. It’s very important to remember combineLatest sends events when any of its inner Observables sends an event. So… when you want to respond to button tap is the wrong idea to mix it in combineLatest.

If you want to read more what are the differences between combineLatest, withLatestFrom and zip you can find an article here πŸ™‚.

#2 – Observable should be lazy

Observable by its nature is a lazy sequence. It shouldn’t run any logic until a subscription. Sometimes you need to wrap an existing API within an Observable:

It’s fine to use just to wrap a single value. However, you run all the logic to calculate the value before a subscription. If you have used deferred the calculation would be moved until some Observer subscribes to your Observable:

You can read more about create, just & deferred here

#3 – Using wrong DisposeBag

DisposeBag is an awesome tool to store multiple Disposable and dispose them at deinit. However, it’s crucial to consider when do you want to cancel old subscriptions.

Typical use-case of that is binding the cell with data from CellViewModel:

The above example my looks fine, but there is a big bug inside. Since we’re adding the disposable into self.disposeBag you gonna have multiple outdated subscriptions when a user starts scrolling the tableView.

You should add the disposable into cell’s disposeBag and deallocate it on cell reusing (you need to override prepareForReuse):

#4 – Not using drivers on UI

Traits are awesome because they help communicate and ensure in compile time our assumptions. Take a Driver for example. Its main purpose is to be used at the UI part of the application.

I obey a rule that all sequences which UIViewController or UIView subscribes to should be a Driver.

Why?

With Rx, it’s very easy to change a queue/thread. "With Great Power Comes Great Responsibility" Uncle Ben used to say. As a result, sometimes you can change the thread by a mistake and forget to call observeOn(MainScheduler.instance) before touching the UI. As a result, you have a crash… πŸ’₯

If you use Driver instead, transforming an Observable into Driver automatically adds observeOn(MainScheduler.instance). You don’t need to remember about it.

Small change inside the interface of the protocol protects the app from any unexpected thread changes and crashes…

#5 – Error handling

Observable is terminated whenever it sends completed or error event. It is one of the Observable traits. When I read this for the first time I didn’t see what are the consequences.

flatMap sends all the events from given Observable into the "original" pipe. All is the key word here. It forwards next events and errors as well.

When login function throws an error flatMap forwards the error into to the main sequence which is the loginAtButtonTap. Whenever an Observable sequence sends an error it stops sending new items. As the result, the app will stop responding to button taps.

To prevent terminating of loginAtButtonTap you can for example use Result<T> type to have an Observable<Result<User>> or to use materialize(). You can read more about errors in RxSwift here.

#6 – Subscribing multiple times into 1 Observable

Observable is immutable class. Every operator returns a new Observable object and doesn’t modify the original. However, sometimes you need to share the results between few Observables, for example:

Assuming the itemsProvider calls a REST API to receive items the above code would call the request twice. When you subscribe to items and numberOfItems you would call itemsProvider twice because items & count are 2 different Observables.

To share the results from itemsProvider you should use share or shareReplay(1):

To read more about share, shareReplay(:) go here and here.

#7 – Overusing subjects & variables

Variables and Subjects are a great tool, however, their usage should be limited. I don’t want to say you should avoid them at all cost, however, remember when you use subjects & variables you use a "mutable variables" in Rx world.

Subjects are the "mutable variables" of the Rx world and in most cases you do not need them. – Erik Meijer

Remember that most of the time you can replace Subject with some operators like merge, concat, publish & refCount, defer and many others. If you want to read more when you should use a subject and when you should not I can recommend you this article however it is from Rx.NET world.

References

Title image – Flickr – becca.peterson26