Reactive Programming is the new hottest topic for mobile app development these days. The basic idea of Reactive programming is, it focuses on asynchronous data streams, observe changes in underlying data and react accordingly using functional and declarative apis. The main advantage of this approach is it reduces global state and programmers can focus more on the business logic than worrying about state and its side effects.

What is Reactive programming ?

Reactive programming is an declarative programming paradigm concerned with data streams and the propagation of change. This means that it becomes possible to express static (e.g. arrays) or dynamic (e.g. event emitters) data streams with ease via the employed programming language(s).

— https://en.wikipedia.org/wiki/Reactive_programming.

ReactiveX website describes it as a “combination of the best ideas from the Observer pattern, the Iterator pattern, and functional programming”. All these patterns are available in Swift and can be used to achieve similar results, for example using key-value observers or using didSet on properties etc. but it is hard to implement them correctly as we need to take care of threading, adding-removing observers, combining with other properties to form correct results etc.

RxSwift is the swift implementation of popular Reactive Extensions (Rx) library created by Microsoft

ReactiveX is a cross platform library for programming with asynchronous data streams and has similar implementations available in other languages like RxJava, RxJs, Rx.Net etc. Once you learn the concepts in one language it can be applied to other languages or platforms.

Reactive Extensions or ReactiveX

as per the official website “ReactiveX is a library for composing asynchronous and event-based programs by using observable sequences.”

Lets decompose the terms asynchronous, event-based and observable sequences:

Asynchronous: It is a means of parallel programming in which each a unit of work (task or function) runs separately from the main application thread and notifies the calling thread of its completion, failure or progress. The main benefits are improved performance and responsiveness.

Event-based: This is a programming paradigm where the flow of execution is determined by events triggered by actions (example: user interaction, push notifications, network response etc). For example tap on the button it will trigger an event and call IBAction or function which will do something.

Observable Sequences: Sequence of data or events which can be subscribed and can be extended by applying different Rx operators like map, filter, flatMap etc. It’s the core concept of Rx, we will learn about it in detail later.

As stated in reactive extension documentation

“Reactive programming extends the Observer pattern to support sequences of data and/or events and adds operators that allow you to compose sequences together declaratively while abstracting away concerns about things like low-level threading, synchronization, thread-safety, concurrent data structures, and non-blocking I/O.”

source: reactivex.io, digram explaining observable sequences

Why Use Reactive Programming?

Rx support functional programming , facilitating writing clean code using rx operators like map, flatMap, filter etc. The observable data sequences can be supplied as input to another observable sequence using declarative code. Even multiple streams can be combined and passed as a single stream.

, facilitating writing clean code using rx operators like map, flatMap, filter etc. The observable data sequences can be supplied as input to another observable sequence using declarative code. Even multiple streams can be combined and passed as a single stream. Simplified asynchronous programming with declarative code which implements complex programs in few lines of code.

with code which implements complex programs in few lines of code. Composing asynchronous event streams using operators like merge , zip , combineLatest etc. in elegant way to create powerful abstractions.

using operators like , , etc. in elegant way to create powerful abstractions. Less global state and more focus on business logic than managing implementation details.

than managing implementation details. Unified Error handling where errors coming from different observable sequences are handled properly in a unified way.

where errors coming from different observable sequences are handled properly in a unified way. Observables and Schedulers in ReactiveX allow the programmer to abstract away low-level threading, synchronization, and concurrency issues.

Observable and Observer

Observable: Observables are the core of Reactive Programming. Observable is called as “Observable sequence” in RxSwift and “Observable streams” in other platforms but they are the same thing. Observable is equivalent to sequence in Swift. Observables are nothing but a sequence of data or elements with some special abilities. The most important one is that it can receive the data asynchronously.

Data sequences can take many forms, such as a sequence of data in json format from the web service, web services requests, system notifications, or a series of events such as user input or button taps. RxSwift represents all these data sequences as Observable sequences. Sequences in RxSwift are described by a push based interface (aka callback).

Observer: An observer can subscribe to these observable sequences to receive asynchronous notifications as new data arrive to perform some operation.

Observer subscribes to the observable sequence. Then the observer reacts to whatever element or sequence of elements the observable emits, till the sequence completes normally or terminated by some error event.

Lifecycle of an observable

Image 1: Observable Sequence completing normally. Image2: Observable Sequence terminating with an error

As described by the sequence diagrams above, Observable can emit one or more elements till the sequence completes normally or terminated with an error .

Primarily there three types of events an observable can emit which will be subscribed by the observer . It is described by the Event enum in RxSwift library as:

public enum Event<Element> {

/// Next element is produced.

case next(Element)



/// Sequence terminated with an error.

case error(Swift.Error)



/// Sequence completed successfully.

case completed

}

onNext(_ element: E): This method is called whenever whenever the Observable emits an element of type E . Observable can call this method one or more times till the sequence completes.

This method is called whenever whenever the emits an of type . Observable can call this method one or more times till the sequence completes. onCompleted(): This method is called by source observable after the observable has emitted all of its elements with onNext: method without any occurrence of error . This simply indicates that the observable sequence has completed successfully and no elements will be emitted after this method by the observable.

This method is called by source observable after the observable has emitted all of its elements with method without any occurrence of . This simply indicates that the has completed successfully and no elements will be emitted after this method by the observable. onError(_ error: Swift.Error): This method gets called by observable whenever it encounters an error while emitting an elements or fails to generate expected data. No further calls will be made to onNext: or onCompleted after the error event occurs. An error of Swift.Error type is provided with onError: method to share the details of the error to the observer.

By the terms of the Observable contract, it may call onNext zero or more times, and then may follow those calls with a call to either onCompleted or onError but not both, which will be its last call.

Hot vs Cold Observable:

Observables can be hot or cold type depending on the nature of emission produced by the Observable .

The hot observable can begin emitting items as soon as it is created and have their data produced by the external sources like button taps, search bar text etc. These event happens independently of any subscriber. Observable will emit data even if there is no observer initially and observers can subscribe later will receives current events as they happen.

A cold observable, on the other hand, waits until an observer subscribes to it before it begins to emit items, and starts pushing values to the observers when subscribe is called. Network requests are the good example of cold observable where observables starts pushing data only after observer subscribes to the observable and no requests will be made till observer subscribe to the observable.

How to create an observable?

Let’s dive into some code now, we will learn how to create an observable using different methods available in RxSwift. The methods are called called as Operators in RxSwift.

Observable.just(): This method returns an observable sequence that contains a single element.

let observable: Observable<String> = Observable.just("Hello RxSwift")

Above example shows how to create observable of type String or Observable<String> which emits a String called “Hello RxSwift”.

2. Observable.of(): This method creates a new Observable instance with a variable number of elements. The sequence is synchronous means it will maintain the order of emitted values.

let observable: Observable<Int> = Observable.of(1, 2, 3, 4, 5)

In above example we are creating an observable sequence of Int values which starts from 1 and emits till value 5.

3. Observable.from(): This method takes array of elements like String, Int etc. and converts an array into an observable sequence .

let observable: Observable<Int> = Observable.from([1, 2, 3, 4, 5])

In the above example above Observable.just() method takes the array of Int values [1, 2, 3, 4, 5] and coverts the array into Observable sequence of Int values. Notice the return type is Observable<Int> not Observable<[Int> as Int array values will be emitted in sequence individually.

4. Observable.create(): We can create an Observable from scratch by using the Create function with some custom logic. We pass this create operator a function that accepts the observer as its parameter. Inside this function we call the observer’s onNext , onCompleted or onError methods appropriately to make it behave it like Observable . This is an example of Cold Observable as this method will not emit any values until subscribe is called by the observer.

For example, this function can be used to convert the network response into Observable sequence after JSON parsing is done by passing the model object in onNext method or pass the error in onError method.

let observable: Observable<String> = Observable.create { observer -> Disposable in

observer.onNext("Hello RxSwift")

observer.onCompleted()

return Disposables.create {}

}

Below marble digram from the reactivex.io site shows create operator in action.

Observable.create marble diagram

Subscribing to Observables:

As we learned earlier, observers can subscribe to observable sequence to receive event notification for the data as they arrive. More importantly an observable won’t emit any values until it has any subscribers. We can observe the values of an observable by calling subscribe() function.

In the above example, subscribe method takes escaping closure that takes an Event<String> enum which has 3 cases as discussed in observer section. We can see output printed 3 “next” string values (aka emoji’s “😀”, “😎”, “😛”) in the console and at last “completed” event gets printed which signals the end of sequence.

subscribe method also has separate handler for onNext, onCompleted and onError event to handle next , error and completed event separately.

subscribe onNext, onCompleted, onError event handler example

Disposing Observables using DisposeBag

In the above example when a sequence sends the completed or error event all the resources used by observable elements will be freed.

The subscribe method returns a Disposable type which is a protocol containing single method dispose() it can be used to cancel the subscription manually which will cancel production of sequence elements and free resources immediately.

dispose() method example

If a sequence terminates in finite time, not calling dispose won't cause any permanent resource leaks, for example in above example it prints 1, 2, 3, completed then gets disposed.

If the sequence is not finite then it can cause memory leaks if the resources are not deallocated hence it’s very important to release the resources by adding it to the DisposeBag

DisposeBag: In RxSwift there is a concept of DisposeBag which accumulates all the disposables and call the dispose method when the DisposeBag object gets deallocated. It’s a standard practice to add all the subscription to disposeBag using disposed(by:) method provided by subscription even if the subscription in finite.

In above example we have TodoListViewModel class which loads the TodoList from the NetworkService . In TodoListViewModel we have created DisposeBag instance which stores the subscription created by subscribing to the Observable<[String]> returned by NetworkService.loadTodoList() method using disposed(by: disposeBag) . As the TodoListViewModel will be deallocated the disposeBag object will call dispose on all of it’s subscriptions and all the subscriptions will be terminated.

Schedulers: observeOn and subscribeOn

Schedulers abstract away the mechanism for performing work in RxSwift. In iOS we have different mechanisms like current thread , main queue , dispatch queues , operation queues etc. which helps us to achieve concurrency or perform some task. Schedulers is basically a wrapper on these mechanisms to perform the work in RxSwift.

There are two main operators that work with schedulers, observeOn and subscribeOn .

observeOn: This operator is used if want to observe the result of some computation on different thread or perform some task on different thread. If we don’t use observeOn then the task will be performed on the current thread. Most of the times we will be using observeOn to perform the tasks in RxSwift.

Below is the example on how to use observeOn:

subscribeOn: this method is used when we want to create observable sequence on some specific scheduler. When we use subscribeOn the subscription will happen on the specified scheduler given in the subscribeOn method so that it will starts to create observable sequence and also call dispose on this specific scheduler.

In case subscribeOn isn't explicitly specified, the subscribe closure (closure passed to Observable.create ) will be called on the same thread/scheduler on which subscribe(onNext:) or subscribe is called.

In case subscribeOn isn't explicitly specified, the dispose method will be called on the same thread/scheduler that initiated disposing.

we can simply change the loadPost example above by using subscribeOn and observeOn like below:

func getTodoList() { let postsObservable:Observable<[String]> = NetworkService.loadTodoList() postsObservable

.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .default))

.observeOn(MainScheduler.instance)

.subscribe(onNext: { todoList in

print("TodoList: \(todoList)")

}, onError: { (error) in

print(error.localizedDescription)

}).disposed(by: disposeBag)

}

Operators in Rx:

The real power comes from the operators in RxSwift. Operators can be used in between the source Observable and the ultimate Subscriber to manipulate emitted elements. Using the operators we can modify, merge, filter or combine multiple observable sequences together.

Rx has vast collection of powerful operators that are categorised depending on the purpose they serve. We can achieve any complex data stream by combining multiple operators together.

We have already learned about some of the operators like just, create, filter, observeOn, subscribeOn earlier 😀

Let’s see some common example of using the operator: Map and FlatMap

map example from rxmarbles.com

let disposeBag = DisposeBag() let observable = Observable<Int>.of(1, 2, 3) observable

.map { $0 * 10 }

.subscribe(onNext: { (value) in

print("next: \(value)")

})

.disposed(by: disposeBag)

as we can see map applies the common operation (value * 10) to all the incoming source observable elements and return the resulting Observable to the subscriber.

FlatMap transforms the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable

The FlatMap operator transforms an Observable by applying a function on all the items emitted by the source Observable, the function itself returns an Observable which emits items. FlatMap then merges the emissions of these resulting Observables into own sequence. FlatMap should be used if want to convert different Observable from the course Observable.

let disposeBag = DisposeBag()

let observable = Observable<Int>.of(1, 2, 3) observable

.flatMap { (value: Int) -> Observable<String> in

return Observable.just(String(value))

}

.subscribe(onNext: { (value) in

print("next: \(value)")

})

.disposed(by: disposeBag)

above example uses FlatMap to convert Int observable sequence into String Observable sequence.

It’s hard to cover all the operators in this post. There is site called rxmarbles.com which shows interactive implementation of different operators. Do checkout the site and operators page from reactivex.io site to learn more about the operators.

Conclusion:

Reactive Programming is really powerful concept and can solve many issues like state and threading with simple and declarative programming model. It has a steep learning curve but once we learn the basics, it’s easy to apply to solve really complex problems in software development. In this post we learned about the importance of reactive programming and how it solves the common issues using declarative and asynchronous code with unified API. Basics of reactive programming using RxSwift and basic elements of reactive programming like, Observable and Observer, Schedulers and Operators etc.

Thanks for reading! If you enjoyed this story, please click the 👏 button and share to find others! Feel free to leave a comment 💬 below.