RxSwift For Dummies 🐣 Part 1
Edit 02.02.2017: This post was updated to Swift 3.0 and RxSwift 3.2
RxSwift is one of those things you have to try yourself to really start appreciating. It’s the one piece of the puzzle that I was missing to glue all the patterns like MVVM, VIPER, Coordinators/Routing.
It’s hard to express what RxSwift really is, because it does a lot. In general it serves as a great observer pattern with a mix of functional and reactive programming. It’s important to say what it isn’t and it isn’t Functional Reactive Programming in it’s original definition. It’s heavily inspired on FRP, so we can say that it contains Reactive and Functional features.
If you don’t know what FRP is, don’t worry for now - you’ll be able to discover it yourself in this tutorial. You’ll gradually learn what Functional and Reactive mean in the FRP.
Digging through RxSwift made me feel enlightened and saved, but also massively confused. Trust me, you’ll feel the same.
It takes a couple of hours to get used to the idea, but when you do, you don’t want to go back.
In this tutorial, I’ll try to save you these precious hours by explaining everything step by step… You know, like to a dummy 😜
You just need some decent knowledge of Swift and UIKit.
UI programming is mostly about reacting to some asynchronous tasks. We’re taught to implement that with observer patterns: I’m pretty sure you’re familiar with delegates by now. Delegating is a cool pattern, but it gets really tiring…
- Delegating is a lot of boilerplate code: creating a protocol, creating a delegate variable, implementing protocol, setting the delegate
- The boilerplate reptition often makes you forget things, like setting the delegate (
object.delegate = self)
- The cognitive load is quite high: it takes quite a lot of jumping through files to find out what’s what
RxSwift takes care of that and more! It enables you to create observer patterns in a declarative way (reduces cognitive load) and without any boilerplate code.
I’ve just started a project, I didn’t create one delegate.
Ok, enough talking, let’s get to it, but let’s start simple.
Here’s a basic example. We have a
runExample method that does something with RxSwift when called. Let’s try to understand what’s happening here.
Let’s start from the basic building block in RxSwift: the
Observable. It’s actually pretty simple: the
Observable does some work and observers can react to it.
Ok, we have an
Observable. This is a cold ❄️ observable: it will start executing only when an observer subscribes. A hot 🔥 observable executes even if it doesn’t have any observers.
We’ll cover the difference and examples in the next parts, so don’t worry, but for now you have to understand that: the
Hello dummy 🐣 value will not be emitted just because you instantiated an ❄️
Observable object. The ❄️
Observable is frozen and will start executing only when you add an observer.
Let’s analyze step by step what’s happening:
Observable executes code on the main thread (unless programmed otherwise) so let’s use a simple
DispatchQueue to not block it. RxSwift has a mechanism called Schedulers that we could use instead, but let’s leave that for later when you’re less of a dummy 🐔.
Observable’s time of work is also called a sequence. Throughout it’s sequence it can send an infinite number of elements and we use the
onNext method to emit these.
When it’s finished it can send a
Error event, after which it cannot produce more elements and it releases the closure along with it’s references.
Observable has to return a
Disposables.create() if you don’t need to dispose of anything.
If you look into the
NopDisposable implementation it does completely nothing - just empty methods.
Disposable that needs to be returned in the
Observable is used to clean up the
Observable if it doesn’t have a chance to complete the work normally. For example you can use the
Disposable is called only when an
Observer is disposed of prematurely: when it gets deallocated, or
dispose() is called manually. Most of the times the
dispose() is called automatically thanks to Dispose Bags. A little lost? Don’t worry, you’ll be able to implement that yourself on a more concrete example.
Observable is cold ❄️. It won’t start executing until we start observing it.
That’s the way you subscribe. Subscription is created and a
Disposable (a record of that subscription) is returned by the
Observable has started work and after 10 seconds you’ll see this printed out:
subscribe(onNext:) will only react to
Next events. You can also use
Dispose Bag 🗑
The only cryptic thing here is the
Dispose bags are used to return ARC like behavior to RX. When a DisposeBag is deallocated, it will call dispose on each of the added disposables.
You add the
Disposables you create when you subscribe to the bag. When the bag’s
deinit is called (for example when the
ExampleClass object gets deallocated) the
Disposables (subscriptions) that didn’t finish will be disposed of.
It’s used to dispose of old references that you pass in the closure and resources that are not needed anymore: for example an open HTTP connection, a database connection or a cache.
If you don’t understand now, don’t worry, a better example is coming.
create is just one of many ways to create an
Observable. Take a look into ReactiveX official documentation for a list of operators. Let’s take a look at some of them.
just just creates an observable that emits one value once and that’s it. So the sequence in that example would be:
interval is a very specific operator that increments an
Int from 0 every
0.3 (in this example) seconds. The scheduler is used to define the threading/async behavior.
repeat repeats a given value infinitely. Again, you can control the threading behavior with a
As you probably noticed, these are not very exciting, but it’s good to know that there are other operators. One more important thing to notice is that it’s a start of the functional part of RxSwift.
Real life example
Ok, let’s wrap this up and let’s do a quick example. Our knowledge of RxSwift is quite limited, so let’s use a simple
MVC case. Let’s create a model that will create an
Observable that fetches data from google.com. Fun! 🎉
That’s pretty simple: the
createGoogleDataObservable creates an
Observable we can subscribe to. The
Observable creates a data task and fetches the google.com website.
The data task of
URLSession is executed on a background thread, so we need to update Observers on the UI queue. Remember that we could use schedulers, but I’ll cover that in a more advanced stage.
Disposable is a great mechanism: if the observer stops observing the data task will be cancelled.
Now the observer part:
Amazing, huh? No protocols, no delegates, just a declarative definition of what should happen when there’s a new event.
Don’t forget about
[weak self] or
[unowned self] in the closure to avoid retain cycles.
There’s a more reactive way to implement setting the text that’s called binding, but we’re too 🐣 to get into that now.
Dispose Bag Example
As you might’ve noticed, the
disposeBag is an instance variable of our
When the view controller gets deinitialized, it will also release the
disposeBag is released, it’s
deinit will be called and our
AnonymousDisposable (created using Disposables.create(with:)) will be called on our
Observable and the data task will be cancelled and the connection will be closed if it didn’t have a chance to finish!
I hope this clearly explains the mechanism of dispose bags.
This wraps it up. You’ve learned how to create observables and observers, how disposing works and hopefully you can see how this is better than the usual observer patterns.
Part 2 is about the whole functional part in RxSwift - operators.
Update: This post was updated to Swift 3.0 & RxSwift 3.2 by Yogish
A passionate iOS dev always trying to get to the bottom of stuff.