It’s time to start your journey into Reactive Programming! Your life will never be the same again. Here’s what’s going to happen: I am going to attempt to explain concepts found in RxSwift (which I’ve been working on for about 6 months) in the funniest, easiest and most memorable ways that I possibly can. So many people have told me that they’ve started learning Rx, but just couldn’t find the time or energy to continue.

Let’s do this.

You are a dog. Your master may, or may not have food. If they do have food, are thinking about food, or even looked at food, then you want to know! You want to know immediately so you can do your best dance moves and dress up disco-style so you can eat. This is your life, this is your mission.

Working with observables is a lot like that. Things may or may not happen and when they do, they might have a value or they might not. Either way, they provide us with one class to handle pretty much any type, and we can react to it.

Usually in iOS we would create a data model, put it somewhere and setup our view. The problem is we want a chance to respond when that data changes: someone just liked a post, your dog friend just found a bone or you can sense your greatest nemesis and need to tell the world: the cat.

We can achieve in traditional ways: we can have a delegate (something that responds to specific events and handles them), we can use notification centre or use callbacks. With Rx we’ll use observables!

In this tutorial we’ll take a look at them in their basic form, mess around with them for a bit and then talk about how to make it better.

Our 1st Observable

Let’s create a single view application and import RxSwift into our project using Cocoapods or Carthage.


1
import RxSwift

Let’s imagine we wanted to make a translation app, one that takes dog-speak (the most advanced and refined form of communication) and translates it into weird, human sounds that they will understand. Usually, we’d just make a String variable, but with Rx we are dealing with Observables which are essentially values that change over time. Time is important as we don’t know where or when things will change:


1
let dogToSpeechTest = Observable<String>.just("Woof")

Here we are using generics with the ‘<>‘ syntax, specifying which type we’re dealing with. We use the handy ‘.just()’ method to provide our observable with an initial value.

We might also want to send an array of messages to our slow-to-understand owners :


1
let dogToSpeakArray = Observable<[String]>.from(["Get", "me", "food"])

We use the ‘.from()’ operator to create a sequence of events from an array.

The thing is, what can we actually do with these? Well, we can subscribe to them. We’ll take each word and translate it when spoken and update the UI!

Observables give us access to the following:

  • onNext – the next value has arrived, something was changed, here is the latest – just like a notification
  • onError – there was a problem here is your chance to respond to the error
  • onCompleted – this task is done
  • onDisposed – we’re getting rid of the subscription to this observable as it’s not needed

Most of the time you just want the value from ‘next’. Every time one of the values from our observables changes (a network call updated them, some logic made it change) then if we were subscribed to them we would get passed that value in the ‘onNext’ function as a parameter. Let’s look at a full subscription for now:


1
2
3
4
5
6
7
8
9
10
11
12
let dogToSpeechTest = Observable.just("Woof")
    .subscribe(onNext: { bark in
    // We have our next bark
    }, onError: { barkError in
    // There was a problem
    }, onCompleted: {
    print("Woof - completed")
       
    }) {
       
    print("Disposed")
    }

We’ve created a variable called goToSpeechTest again and subscribed to it. The subscribe function will listen for next, error, completed and disposed events. If we have handlers setup we could respond to each of these here. OnNext is the one we really care about. We could update text with it, play a sound, send it to the translator or anything. The best part is that it is all right here in this one variable rather than some complex logic somewhere else, and we’re just getting started!

We could also just subscribe to the onNext event for simplicity:

 


1
2
3
4
let dogToSpeechTest = Observable.just("Woof")
    .subscribe(onNext: { bark in
    // We have our next bark
    })

So when we subscribe to this there is huge potential for memory leaks. How long should we stay subscribed, how should it be disposed of? Normal Automatic Reference Counting isn’t going to help us here so we need to dispose of this subscription. In Rx land, we use DisposeBag for this. It is just a simple way to handle the tidying up of subscriptions. It can look a bit weird at first, but hang in there:

 


1
2
3
4
5
6
7
8
// Create our dispose bag at the top of the class
let disposeBag = DisposeBag()

// Add the disposed by method to the end of the chain
let dogToSpeechTest = Observable.just("Woof")
    .subscribe(onNext: { bark in
    // We have our next bark
    }).disposed(by: disposeBag)

So now we have a subscription that will listen to barks and can send them off to the translator! We’ve taken care of memory leaks as well and learned about the different events in Rx subscriptions. In the following tutorials we’re going to build up to more real-life scenarios such as how to integrate these into view models and working with overall app architecture.