Get started with RxSwift and reactive programming

The Reactive programming is getting popular as it is a completely different paradigm. Check out this article for a quick intro into RxSwift.The Reactive programming is getting popular as it is a completely different paradigm. Programmers use imperative programming quite a long time and it is prevailing nowadays.

We are observing the RxSwift version 4.0 along with RxCocoa 4.0. The latter is the set of extensions for Cocoa elements such as UITextField, tap events etc.

The key concept in reactive programming is data streams, and propagation via observable sequences. (http://reactivex.io/)

Observable – a structure which emits a certain value over time. A subscriber subscribes to the observable. We can observe an array, string, HTTP request, text change in UITextField.

The basic example of Observable which emits a string.

let observable = Observable<String>.just("Observe me")

_ = observable.subscribe(onNext: { value in
    print("onNext: \(value)")
}, onError: { error in
    print(error)
}, onCompleted: {
    print("Completed")
}) {
    print("Disposed")
}

The observable has 3 types of events:

  • onNext – emits N number of times an event
  • onError – the observable emits an error and terminates
  • onCompleted – the observable completes its work.

From the output above we see next:

onNext: Observe me
Completed
Disposed

The observable emitted a string value, completed itself and was disposed. The disposing is a memory management mechanism used in RxSwift.

We can create a DisposeBag which is retained by some parent object, it can be UIViewController in many cases. And when the object is deallocated,deinit is called then disposebag disposes subscriptions.

And this will look like:

let disposeBag = DisposeBag()

let observable = Observable<String>.just("Observe me")

observable.subscribe(onNext: { value in
    print("onNext: \(value)")
}) {
    print("Disposed")
}
.disposed(by: disposeBag)

You can see that we can omit the error and completion handling.

What about threading on RxSwift? It uses Schedulers. An elegant way to subscribe and observe on different threads.

subscribeOn is used to specify Scheduler of the work before the subscription happens.

observeOn is processing subscription itself.

There are a bunch of schedulers ready to use  MainScheduler, CurrentThreadScheduler, ConcurrentMainScheduler. They are similar to the Grand Central Dispatch.

Let’s create an observable for text input into the UITextField. After a user inputs some text, then a search can generate an HTTP call. Many requests can cause network contamination issues. So we will find a plethora of operators (http://reactivex.io/documentation/operators.html#tree). For instance, throttle would help us filter out many operations.

Adding a simple UITextField to the view controller and with RxCocoa we can access text changes. Such as ‘textField.rx.text’ and it is a ControlProperty:

Sequence of values only represents initial control value and user initiated value changes. Programmatic value changes won’t be reported. It’s properties are: – it never fails – shareReplay(1) behavior

  • it’s stateful, upon subscription (calling subscribe) last element is immediately replayed if it was produced
  • it will Complete sequence on control being deallocated
  • it never errors out
  • it delivers events on MainScheduler.instance

ControlProperty is an example of Hot observable. It would produce sequence of elements no matter if it has a subscriber. And the result is shared between subscribers via the operator shareReplay(1). It means whenever a new observer is subscribed a last value in a sequence would be replayed and thus shared. And it relates to producing heat.

The Cold observable doesn’t produce work or use resources until there is a subscriber. It can be async operations as HTTP requests. And it is not shared by default.

The code for transforming a string sequence from UITextField.

textField.rx.text.orEmpty

.subscribe(onNext: { text in
    print("text: \(text)")
})
.disposed(by: disposeBag)

rx.text – a ControlProperty to observe text changes

orEmpty – transforms control property to from String? → String

Make sure that disposeBag is declared on a viewcontroller level, not a local variable. So the subscription would have the same lifecycle with UIViewController.

textField.rx.text.orEmpty
.throttle(1, scheduler: MainScheduler.instance)
.map({ text in
    return text.count
})
.subscribe(onNext: { text in
    print("text length: \(text)")
})
.disposed(by: disposeBag)

The throttling of input can be achieved with the operator whichthrottle(1, scheduler: MainScheduler.instance) simply filters out the emitted events in 1-second duration between emitting many values.

The map operator transforms values send it further to the subscriber.

.map({ text in
    return text.count
})

can be written like .map { $0.count }

So this simple example gave an overview of the technology. The one side of using Reactive patterns is data binding. In the MVVM architecture, the RxSwift can process receiving events from the user interface and bind values.

textField.rx.text.orEmpty
.map { "character count: \($0.count)" }
.bind(to: textLabel.rx.text)
.disposed(by: disposeBag)

This example shows a binding between the text emitted from the text field and a text variable on a label. In such a way, we have easy access to event streams and direction of using it via binders.

The RxSwift is a powerful library with a unique paradigm. We can write a succinct and easy to read code. But the developer still needs to keep in mind retain cycles, error handling and nature of observables aka hot and cold.

2 thoughts on “Get started with RxSwift and reactive programming

  1. Pingback: Magic of RxSwift. Rx Operators | agostini.tech

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.