Code faster with RxSwift
People usually talk about reactive programming and, specifically, RxSwift as the ultimate way to describe application logic — event chains, error handling, asynchrony. But don’t forget that RxSwift is also a tool which allows you to add a reactive extension to anything.
RxSwift has a rather large and creative community. RxSwiftCommunity’s github profile currently has 55 repositories of various sizes and purposes. At the root of all of them is reactive programming.
Below I talk about dependencies that have become mandatory for my Podfile.
We all love to overlap a password field with the keyboard, don’t we?
I won’t count lines of code or describe my disgust about using
NotificationCenter. Just see how cool changes of the keyboard height are when expressed via the concept of events sequence. Let me remind you that all Rx operators are available here. You can use
debounce, or combine with another
Observable here and so on. Here is an example of my favorite declarative piece of code:
I could explain that I hide
backgroundFadeView when the keyboard is hidden and show it if the keyboard is visible. But you understood that within the first glance.
It’s a really common situation, when
UIButton is not enough. Let’s compare a syntax:
Again, I could explain that we filter only
.ended gestures and compute translation. But it is obvious, even if you are unfamiliar with this framework or RxSwift.
The problem with this old Cocoa pattern is the smearing code through all classes. To figure out everything that happens with your
view, you have to look through all classes and find code, which actually should be concentrated in one place. You need:
- write callback function
- configure it (set
- add it to view
The first item is the most terrible. The class will have a private function that will be passed to
#selector(). Is it a real function? No, this is a callback that has a name for no reason. This function must be anonymous (e.g. closure) to restrict the programmer from calling it manually.
The same problem occurs with util functions like
setupPageControl, where the component’s setup code is placed. These are not functions in the real sense of the word. They do not express class behavior. We just needed to somehow separate the code, “to improve its readability”. At the same time, the class size has grown, the meaning becomes less clear, and real business logic is now difficult to understand.
With RxGesture, all your code — creation, configuration, callback — is concentrated in one place. You can quickly look through and change it while avoiding meaningless utility functions that are a result of a vain attempt to keep your code separate.
The neatest part. How to work with the most important thing in every iOS dev’s life(
UICollectionView)? Lots of code for an important problem.
We have code spread throughout the class and again, delegates, as well as the absolutely useless methods of
numberOfSections. A section should be expressed by language tools, for instance, a generic struct
SectionModel <String, Int>, which takes a name of section and an array of its elements. Now a number of sections and cells could be inferred implicitly. The length of the array is always equal to a number of sections, and the length of the nested arrays — a number of cells.
And no need to touch the array for the item by
IndexPath. Keep it simple. Here is the closure
configureCell in which a model serves as a parameter. A programmer has to just make a cell from it.
There is an additional bonus — diff algorithm, which works with O(N) complexity. We will dig into it in the next article. Simply emit a new array of sections and the framework will update only needed places. No more imperative calls to
reloadData. Out-of-the-box animation updates and convenient closures instead of outdated delegates are also supported. It has never been so handy for me to work with a footer activity indicator in
RxSwift implements the reactiveX.io specification but is not very open for new ideas. But that’s not a blocker for the community, thus there is the repository of custom operators. They are all rather small and simple, however, they help me to avoid writing dozens of lines of code every day.
If you already have experience with Rx, you are probably interested about best error handling practices. Someone will advise the Railway Pattern and the
Result type instead of the
onError essential callback system.
My most preferred way is splitting a sequence of events into errors and elements sequences. Using this approach, you won’t get any observable completed or failed with error unless you want it.
A great framework to deal with navigation problems in a reactive way. Article about it is coming soon, follow me if you don’t want to miss it :)
It is easy to see that reactive frameworks combine similar syntax and motivation. People want to write less code without losing readability. And RxSwift, with its way of working with asynchronous events, really allows you to do so. You only need one line, where in the imperative style you may need ten.
I strongly advise you to browse other repositories in RxSwiftCommunity. You will find reactive extensions for many iOS parts, and several architectures, including Unidirectional Data Flow. It is always useful to know alternative ways of solving daily tasks. Maybe they will be better than yours?
If you enjoyed this story, please give it a clap and share to help others find it! Feel free to leave a comment below. Follow me to read more about RxSwift.