Getting Started with RxSwift (The Basics)
Learn the basics of RxSwift and how it can simplify iOS app development. Improve your coding skills with this comprehensive guide.
Reactive programming is an asynchronous programming paradigm that deals with data streams and the propagation of change.
RxSwift is a library for working with asynchronous code that presents events as streams of events with the ability to subscribe to them and allows you to apply functional programming approaches to them, which greatly simplifies working with complex sequences of asynchronous events.
Why should you use RxSwift?
RxSwift organizes work with streams of events and connections between objects.
The simplest and most obvious example is bindings: you can update the interface by simply setting a new value to a variable in the ViewModel
. Thus, the interface becomes data-driven.
In addition, RxSwift allows you to describe the system in a declarative style, which simplifies the code and improves its readability. RxSwift is also constantly receiving new updates, fixing minor bugs, adding features from new Swift versions and new bindings.
And RxSwift is open source, you can keep track of all the changes.
RxSwift Basic Concepts
There are three main types of Rx code components:
- Observables,
- Operators, and
- Schedulers.
Observables
An Observable is a sequence with some special features. One of these features – and perhaps the most essential – is asynchronous.
Observables generate events over time, which is referred to as emitting. Events may include values such as numbers or instances of a custom type, or they might be recognized gestures such as taps.
Operators
The Observable class contains several helper methods that can perform various operations on the elements of the sequence.
Since they have no side effects, they can be combined, which allows you to build quite complex logic in a declarative style.
Scheduler
The scheduler allows us to run our observables on specific threads. There are two ways to set the observable scheduler: observeOn()
and subscribeOn()
.
SubscribeOn()
is responsible for which thread the entire observable process will run on until its events reach the subscriber. As you might guess, ObserveOn()
deals with a thread that processes events received from subscriberOn()
.
With scheduler, you can easily download anything from the web on a background thread, and once you get the result, you can go to the main thread and affect the UI.
An RxSwift Example:
Now that we’ve figured out the basic concepts of the library and understood why we should use it, let’s look at one practical example.
import RxCocoa import UIKit import RxSwift class ViewController: UIViewController { @IBOutlet weak var countLabel: UILabel; @IBOutlet weak var tapButton: UIButton; var count = 0 var disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() countLabel.text = "\(count)" tapButton.rx .tap .throttle(5.0, scheduler: MainScheduler.instance) .subscribe(onNext: { [weak self] in self?.count += 1 self?.countLabel.text = "\(self?.count ?? 0)" }) .disposed(by: disposeBag) } }
To simplify this example, let’s make the number on the counter increment when the button is pressed.
For this, first, you need to import the dependencies:
import RxCocoa import RxSwift
Now let’s look at the piece of code in tapButton.rx, focusing on each line.
tapButton.rx .tap .throttle(5.0, scheduler: MainScheduler.instance) .subscribe(onNext: { [weak self] in self?.count += 1 self?.countLabel.text = "\(self?.count ?? 0)" }) .disposed(by: disposeBag) } }
As I mentioned above, RxCocoa provides us with the Rx family of methods that contain ready-made methods that return a ControlEvent
to us.
In this case, we are interested in the tap method. We subscribe to receive events, where we pass a closure to the onNext
parameter, which will be executed when each event occurs.
We are also incrementing the counter and updating the label. Since ControlEvent
is essentially an infinite sequence, it will not have onError
and onComplete
parameters.
We should also mention DisposeBag
separately. When you finish working with a sequence, you need to free memory. When we look at the source of ObservableType
, we should see that the subscribe method returns an object of type Disposable
.
And if you look at its protocol, it turns out that it requires a single disposal method, which, as you might guess from its name, serves this purpose. But manually deleting objects can be tedious, so you should use the DisposeBag
class, and why?
If you are using a subscription and not adding it to the bag, deleting it explicitly, or otherwise completing the observable in some way, then you are likely to get a memory leak.
Therefore, to avoid this, DisposeBag
should be used.
Conclusion
RxSwift is a relatively large library. If you want to familiarize yourself with all APIs, you need to read the documentation, code often, and read the source code.
A detailed study of the RxSwift documentation will not only increase your development efficiency but also deepen your understanding of the Swift language. Therefore, I can wish you all the best in your exploration of RxSwift.