RxSwift For Dummies 🐥 Part 2
TODO: Update to Swift 3.0/RxSwift 3.0. Just some minor syntax changes, everything else is still correct so feel free to explore
Ok, we covered the RxSwift basics in Part 1. Let’s now try and inspect some interesting operators and discover the Functional in FRP.
Let’s start with something I already mentioned, but didn’t really explain: schedulers.
Schedulers are most commonly used to easily tell the observables and observers on which threads/queues should they execute, or send notifications.
The most common operators connected to schedulers you’ll use are
Observable will execute and send notifications on the same thread on which the observer subscribes on.
observeOn specifies a scheduler on which the
Observable will send the events to the observer. It doesn’t change the scheduler (thread/queue) on which it executes.
Let’s take this example, very similar to the one from Part 1:
Let’s assume that the observer is some kind of UI -
We’re dispatching the work to a background queue, to not block the UI.
Then we need to change back to the main queue to update the UI. I hope that you remember that UIKit requires you to update UI elements from the main thread, if you do I’m sure you’re familiar with this dance already.
Let’s refactor it using
We remove the
dispatch_async(dispatch_get_main_queue() and add
.observeOn(MainScheduler.instance). This causes all events to be sent to observers through the main queue - it’s that simple. The
Hello dummy 🐥 element can be safely used to set an UI element, because we’re certain that it’ll be passed on the main queue:
observeOn is probably the most common scheduler operator you’ll use. You want the
Observable to contain all the logic, threading etc. and you want your observer to be stupid and simple. Let’s quickly investigate
subscribeOn though, at it might prove useful.
This is a more advanced operator. You can skip it for now and come back later 🐤
subscribeOn is very similar to
observeOn but it also changes the scheduler on which the
Observable will execute work.
As you can see I deleted the
dispatch_async(dispatch_get_global_queue... in the
Observable and it’s the observer that tells the
Observable to execute on a global queue to not block UI. This of course leads to an exception being thrown because as I mentioned: it causes the
Observable to work on a global queue, but also send events on a global queue, not on the UI queue. We could just add a
dispatch_async on the main queue, but we can also experiment, do something more interesting and add a
.observeOn(MainScheduler.instance) to the
Observable we notice that it solved our problem. Why is it interesting? Because it shows that
subscribeOn in terms of which scheduler is used to send events!
When do we use
observeOn? The most common scenario would be an
Observable that doesn’t execute long tasks (fetching data, calculating etc.) on a different queue/thread and blocks your thread. I don’t imagine that will happen too often, but hey! it’s always worth to know what tools you have in your box 🛠
As a RxSwift beginner it’s fine to stick with
MainScheduler.instance so I’m going to cut here to not distract you too much. You can build your own custom
Scheduler or use one of the already built in ones. Here’s more if you’re that curious. It’s quite simple and natural as it’s just wrapped Grand Central Dispatch and
Ok, so you already know two types of operators: creating operators (
just) and utility operators (
subscribeOn). Let’s inspect some of the transforming operators.
Very simple, yet powerful. Probably the one you’ll use the most.
map operator changes your sequence type. It maps an
Observable so it emits a different type in a way you tell it to. In this example we map an
true and an
This example will print:
scan is more complicated.
scan allows you to change the current element based on the last one emitted. It’s also said to accumulate elements. The
"" passed in the
scan parameter is the seed: the starting value.
Still don’t get it? Why would anyone use it, right?
scan operator to calculate a factorial of
5, which will print
Marin gives us a more useful example of a select/deselect state of a button:
Now that’s something you can use, huh?
Of course, there are more transforming operators, but I think you get the idea now. You can go here to read more.
It’s important to emit values, but it’s also important to skip emitting them when needed - that’s what filtering operators are for.
Decide yourself which ones you want to emit and which ones to skip!
It’s a pretty easy, but useful one.
debounce in this example just skips elements that aren’t at least 2 seconds apart. So if an element will be emitted after
1 second after the last one, it’ll be skipped, if it’s emitted
2.5 seconds after the last one, it’ll be emitted.
Combining operators let you take multiple observators and convert them into one.
merge just passes elements from multiple observables into one (merged) observable.
zip connects an element from each observable into one element.
Now this is a very interesting operator. Let’s say that you have two HTTP requests and you want to wait for them both to finish:
zip will wait for each element in each
Observable to finish and will emit a value that’s a sum of both “requests.
There’s a lot of other interesting operators like
takeUntil, but I think you get the idea by now and you’ll be easily capable to discover them by yourself. The idea was to see how powerful they are and how easily and fast you’re able to mold the sequences in terms of time, conditions or transformations.
This tutorial doesn’t need a concrete example project, but it can be useful to show you how easily you can mix operators.
Let’s do this with a crazy idea: to change background color based on the current time.
You can find more examples in the RxSwfit playgrounds.
Wow, you really know a lot now! The only big thing left to teach you are Subjects.
A passionate iOS dev always trying to get to the bottom of stuff.