These are my learning notes on RxSwift after watching an introductory video course. I’ve sent these notes to a friend of mine who mentors me, and he suggested that I publish them as a blog post. It positively impacted my learning process.
I’ve written all of the definitions in my own words so that I can remember the material better.
After finishing the video course, I had some significant gaps in understanding of the basics. Because I just kept writing the notes, I had a goal to be able to explain the terms, and after finishing, I’ve started to understand them.
I stopped the videos and redid all the examples I saw by myself. This helped a lot, because I learn by doing.
I’ve used Xcode Playgrounds for this. Setting up Playgrounds to work with a 3rd party CocoaPods library is tricky; I’ve tried to use an open source tool to automate the process, but it didn’t support Swift 4, so I did it manually in the end.
The course was in Swift 3 and RxSwift 3. RxSwift 4 was just released and had some significant changes, which I figured out from the documentation.
It was challenging for me to understand the RxSwift’s Getting Started documentation, and after finishing the course and getting some hands-on experience, the documentation became very clear.
I’ve also found marble diagrams very helpful.
Here are the notes:
Observable — an entity that emits events with an additional payload.
Observer — an entity that subscribes to the events emitted by the Observable.
Scheduler — an abstraction similar to an operation queue.
There are three types of events that Observable can emit: next, error and completed. For each type of these events, there can be separate Observers.
Observable is also a mechanism for retrieving and transforming the data.
“Rx” stands for Reactive Extensions, which is a set of operators that can be used on the Observables. Here are the operators I’ve tried during the course:
Just — create an Observable around an object or a collection of objects.
Buffer — accumulate a certain amount of events and then emit a collection of them.
FlatMap — emit raw events, that hold payloads of the same type, from a collection of Observables.
Map — transform the emitted items by applying a function to them.
Scan — very similar to the reduce operator; the difference from the Rx’s Reduce operator is that Scan will emit all the intermediate events, while Reduce will emit a single event when an Observable completes.
Distinct — emit an event only if its payload is different from the payload of the previous event.
Filter — emit only those events that pass a test.
CombineLatest — for multiple Observables, on any emission take the latest event from every Observable and combine them with a function.
Merge — for a collection of Observables, emit their events in a single sequence, in the order they come.
StartWith — prepend the emitted sequence with another sequence of events.
Zip — combine events emitted by multiple Observables in pairs: 1, 2, 3 and A, B, C become 1A, 2B, 3C.
Catch — recover from an error and continue the sequence.
Retry — if an error is emitted from an Observable, then resubscribe to it.
ObserveOn — can be used in a scenario when a task on the background thread needs to notify the main thread; this operator lets to specify the scheduler that an Observer will observe the events on.
Subscribe — act on the events that an Observable emits.
SubscribeOn — specify a scheduler where the subscriber will run on.
TakeWhile — similar to the while-true construct; continues to emit the events while these events satisfy a condition.
Because most of the Rx operators operate on Observable and return an Observable, they can be chained.
When an Observer subscribes, the subscribe() method returns a Disposable. Although not required, disposing the observers is highly recommended so that the resources are managed correctly and don’t hang in the memory (leak) when unused. Manually disposing observers is not recommended, and it’s better to use a DisposeBag.
Subjects are entities that are Observers and Observables at the same time. Subjects observe other sequences, and when these have updates, subjects emit their events.
BehaviourSubject — emits the last event to its new subscribers. After that, it will emit every event to them.
PublishSubject — a broadcaster: it will pass all of the events it observes to its observers.
ReplaySubject — acts as a PublishSubject, except that it replays all of the missed events to its new observers.
There are also Traits. Traits are wrappers around read-only Observables.
Single — a Trait that emits only one event or an error. Rather than emitting next/error/completed, Single emits success/error. Useful for HTTP requests, for example.
Completable — emits either a completed event or an error. Useful for cases when we are interested to be notified only when the process completes, and there’s no data.
Driver — a Trait designed for hooking up Observables to the UI. Drivers don’t emit errors, run on the main scheduler, and their side effects are shared between subscribers. Not emitting errors is critical, as Observables unbind themselves after errors, and we don’t want to unbind the UI. Sharing side effects is also important, as multiple UI elements may depend on the same operation, and it might be expensive to run it multiple times.