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