RxSwift: Reactive Extensions for Swift Part 1
In this first part of this blogpost we are going to explore the theory in order to understand RxSwift, specifically ReactiveX. In the second part we are going to apply this concept to create a sample iOS application using RxSwift.
WHAT ARE REACTIVE EXTENSIONS?
“ReactiveX is a combination of the best ideas from the Observer pattern, the Iterator pattern, and functional programming”
OBSERVER AND ITERATOR?
The Observer and Iterator patterns, described in the GoF book, are two patterns used in a Producer/Consumer scenario.
The Iterator Pattern is used to pull data, typically from a Collection of Objects, as long as it implements the iterable interface. This is a synchronous and interactive, I’m reading the current value and asking for the next one till I’m satisfied or the collection ends.
The Observer Pattern is used to Push data, objects that are interested in the data subscribe to receive data when it’s available. This is asynchronous and reactive, when new data is available to the subscribers they are notified with the data.
What ReactiveX explores is the correspondence between this two patterns, and unifies the semantics between them (Observer is Dual to Iterator).
EVENTS, EVENTS EVERYWHERE…
“Rx is that sweet spot between functional and imperative worlds. It enables you to use immutable definitions and pure functions to process snapshots of mutable state in a reliable composable way.”
Rx defines Observables that are a sequences of elements that enable easy composition of asynchronous operations and event/data streams.
Rx allows us to create event/data streams and to compose and transform them with operators. There are operators like filter, map, combine, retry, observe, bindTo, zip, throttle. The list of all the operators is available here: Operators List.
You can also subscribe to any observable stream to perform side effects.
Rx works well with a stateless architecture, data doesn’t need to be actually stored anywhere, it can pass from one system to another applying different transformations from pure functions, a stream transformation into another stream.
EXAMPLE
In this example we are making a search on GitHub, this is an example taken from RxSwift.
let searchResults = searchBar.rx.text.orEmpty
.throttle(0.3, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest { query -> Observable<[Repository]> in
if query.isEmpty {
return .just([])
}
return searchGitHub(query)
.catchErrorJustReturn([])
}
.observeOn(MainScheduler.instance)
We create an observable on the main thread from the searchBar text. This stream is throttled in order to avoid making a request every time the text changes. The stream only send events if the text actually changes. We always receive the latest text entered by the user and if it’s not empty we make a search request.
We can bind this search results to a table view in order to display the results we get when the user updates the search.
searchResults
.bindTo(tableView.rx.items(cellIdentifier: "Cell")) {
(index, repository: Repository, cell) in
cell.textLabel?.text = repository.name
cell.detailTextLabel?.text = repository.url
}
.disposed(by: disposeBag)
Here we can see it working:
RESOURCES:
In here you can find some resources if you want to get started with RxSwift.
Interactive diagrams of Rx Observables
Expert to Expert: Brian Beckman and Erik Meijer – Inside the .NET Reactive Framework (Rx)