Intro to RxSwift
Hi there, if you ever wanted to learn RxSwift, here are basics of it. RxSwift is the part of reactive extensions “family”, and that family consists of other programming languages with “Rx” prefix, here is the list. So, what the hell should that mean to you as an iOS developer? The thing is those Rx libraries almost the same, and same ideology was used when they were created and that means if you learn RxSwift you can easily switch to RxJS or RxJava or any other language with Rx prefix. Here is a quick demo to demonstrate it to you.
Here is the RxJS code. It creates an observable, subscribes to that observable and prints the values of it (Don’t worry I will explain what observable and an observer are):
const observable = Rx.Observable.create(function(observer) { observer.next('Hello'); observer.next('World'); }); const subscribe = observable.subscribe(val => console.log(val));
And the same thing with RxSwift:
let observable = Observable<String>.create{ (observer) in observer.onNext("Hello") observer.onNext("World") return Disposables.create() } observable.subscribe { (val) in print(val) }
So as you can see besides the language syntax it almost the same. Even if this is a simple example, same applies to more complex things.
All right, before getting deep in RxSwift you have to change the way you think when you code. If you’re not familiar with Reactive or Functional programming, it will drive you crazy at the beginning, but don’t worry you will get used to it 😄. The main thing you have to remember is, in Rx world everything is asynchronous and everything is a stream. And since everything is a stream you need to watch, mutate and respond properly to those streams. Imagine this, you are playing a ball with your friend, when you pass him a ball he catches it without you notifying him that you threw him a ball, that happened because he was watching you. That’s reactive way of thinking, he reacts to what you do, without you telling him what are you doing. In an imperative way of thinking, this is different, you always should say to him that you’re passing a ball, otherwise he will not know that you passed a ball(it’s like calling a function catchBall in your friend 😄).
Here is the good article on this topic.
And about asynchronicity of Rx. Actually, that’s what RxSwift solves in iOS development. If you ever wrote the code that works asynchronously it just a pain in the butt, especially in big projects where a bunch of variables from several classes waiting for the particular event to happen. You could handle it with callbacks in a nasty way:
class Blog { private var likedCallbacks: [((Bool)->Void)?] = [] var isLiked = false { didSet { likedCallbacks.forEach { $0?(isLiked) } } } func onLiked(callback: ((Bool) -> Void)?) { likedCallbacks.append(callback) } } class Controller { let blog = Blog() let reader: Reader init() { blog.onLiked { $0 ? print("Yeah!") : print("Ooh") } reader = Reader(blog: blog) } } class Reader { let blog: Blog init(blog: Blog) { self.blog = blog self.blog.isLiked = true } }
This is a very simple example of what I’m talking about, you still have things to do with this code. And here is the same thing but in Rx style:
class RxBlog { let isLiked = Variable<Bool>(false) } class RxController { let blog = RxBlog() let reader: RxReader init() { reader = RxReader(blog: blog) blog.isLiked.asObservable().subscribe(onNext: { $0 ? print("Yeah!") : print("Ooh") }) } } class RxReader { let blog: RxBlog init(blog: RxBlog) { self.blog = blog self.blog.isLiked.value = true } }
Now, let’s talk about the basics. There are only a few things you need to know, they are: Observables, Subscriptions, Subjects, Operators, Schedulers. For now, we’re going to focus on first two.
Observables:
Observables are the foundation of RxSwift. You can imaging observable as a stream of some events, “produced” asynchronously over a period of time. The process of producing is referred as Emitting. We can illustrate it like this:
—–1—–2–3–4——->
Read it from left to right, where arrow represents time, and numbers represent events. Element 1 will be emitted, some time will pass, and then 2 will be emitted, and then 3 and so on. If you’re thinking how much time passed between events, it could be at any point throughout the life of the observable. And if you’re asking when it stops then? It will stop once observable completes or errors out. Observable has 3 event types: OnNext, OnError, OnComplete.
- OnNext events are regular events like 1,2,3 from the previous illustration, so they’re good.
- OnError event speaks for itself. If an error occurs at any time of observable lifecycle then the observable stream will stop.
- OnComplete event also stops the observable stream, you can consider it as “Stream Finished Successfully” event.
Let write some code and see how to create Observable. If you’d like to try everything yourself, go to RxSwift repository on GitHub, download it and open up Rx.xcworkspace and check out the example section.
Here is basic observable that emits only one on OnNext event with the value of 10 followed by OnComplete event meaning that stream finished successfully.
let observable: Observable<Int> = Observable<Int>.just(10)
We create the observable using just operator which emits only one event and stops.
And if you’d like to put more events into your stream you can use of operator.
let observable2 = Observable.of(10, 20, 30)
This time we created an observable stream with 3 OnNext events(10,20,30) with finishing OnComplete event.
And if you’d like to create an observable from an array:
let observable = Observable.from(["Hi","There"])
This time we user from operator which use an array as an input parameter.
And one of the most interesting creating operators is create operator, where you can push your events and control when to complete your stream or when to emit an error.
let observable: Observable<Bool> = Observable.create { observer in observer.onNext(false) observer.onCompleted() observer.onNext(true) return Disposables.create() }
Guess how many OnNext and OnCompleted events were emitted? You were right if you said 1 OnNext and 1 OnCompleted. Because once your stream emits onCompleted or onError event further events won’t be emitted by your observable. So in this example, your observable emits OnNext false event and OnCompeted event. And if you are wondering what the disposable is, for now, you can remember it as a mechanism for releasing observables from memory. I will explain disposables in my next blog post.
Now you know how to create a basic observable, but an observable means nothing without anyone observing it. Here comes subscribing to help you observe your observable.
Subscriptions:
The process of observing an observable is called – Subscribing. You can subscribe to any observable you want and work with those event however you want. And one observable can have multiple subscribers observing it. Let’s work with observables we created before:
let observable2 = Observable.of(10, 20, 30) observable2.subscribe { print($0) }
and here is the output of the code:
next(10) next(20) next(30) completed
As you can see it printed all events the observable2 emitted. But what if you wanted to work only with NEXT events? Here is the solution RxSwift prepared for you:
let observable2 = Observable.of(10, 20, 30) observable2.subscribe(onNext: { print($0) })
Output:
10 20 30
This time raw values and no completed event printed. The key part is onNext parameter in subscribe operators body. And as you may guess besides onNext parameter there are also onError and onComplete parameters. Here is the good example of it:
let observable: Observable<Bool> = Observable.create { observer in observer.onNext(false) observer.onCompleted() observer.onNext(true) return Disposables.create() } observable.subscribe(onNext: { (value) in print("The value is \(value)") }, onError: { (error) in print("Oops, some thing went wrong") }, onCompleted: { print("The stream finished") })
In this example, we subscribed to observable which emits false event and emits completed event, and as we said before onNext true event never emits. Here is the output to prove that:
The value is false The stream finished
Now let’s change this example, what if we put onError instead of onComplete in observable create?
let observable: Observable<Bool> = Observable.create { observer in observer.onNext(false) observer.onError(NSError()) observer.onNext(true) return Disposables.create() } observable.subscribe(onNext: { (value) in print("The value is \(value)") }, onError: { (error) in print("Oops, something went wrong") }, onCompleted: { print("The stream finished") })
Guess what is output?
The value is false Oops, something went wrong
So as you can see onCompleted and onError events prevent further events to emit. And also you can subscribe to those events like you subscribe to onNext event.
That’s it for now, you can play around with RxSwift to learn more. Check out RxSwift documentation. See you in my next blog post about RxSwift where I will tell you about Disposables and Operators.
Leave a comment if you have any questions, or just want to say “Hi”, I will be glad to talk.
Subscribe to get notified of new posts.
Thank you