In yesterday’s post, we walked through how one could take “Enumerable
”,
(or, really, Sequence
) and “Enumerator
”
(really, Iterator
), and turn them into Observable
and
Observer
. These are the two types that underpin most everything in
RxSwift.
In this post, let’s explore a little more about what RxSwift is, and what it isn’t.
Let’s Make a Sandwich
When people colloquially refer to “RxSwift”, they’re often referring to an entire group of projects and technologies. When writing an iOS app, it is certainly possible to use only RxSwift, but that’s like making a sandwich only of bread.
In reality, the beauty of RxSwift from an app developer’s perspective is not the RxSwift “bread”, but rather the meats and condiments inside. More directly, RxSwift is fine, but interaction with things like user interfaces and system frameworks is what makes RxSwift really shine.
One of my favorite uses of RxSwift is to interact with user interfaces.
The taps of a UIButton
are an excellent example of something that can
be exposed as an Observable
.
However, using only RxSwift, there isn’t a terribly straightforward
way to expose a button tap as an Observable. It’s certainly doable, but
would require creating an entire object just to be the receiver of the
button’s .touchUpInside
action
. That’s a lot of housekeeping to
get to one button’s tap.
Thankfully, many of these menial tasks are already taken care of. Instead of having to worry about writing an entire object to worry about a button tap, you can leverage a project that’s built upon RxSwift.
RxCocoa
RxCocoa is sort of part of RxSwift, though it’s sort of not.
It’s a separate target, and must be import
ed on its own, but the source
lives within the RxSwift repository.
It’s RxCocoa that brings all of these convenient bindings to the table. Thus, instead of having to do a whole bunch of housekeeping in order to get to a button tap, one can just do this:
let disposeBag = DisposeBag()
let button = UIButton()
button.rx.tap
.subscribe(onNext: { _ in
print("Tap!")
})
.disposed(by: disposeBag)
That is so nice, and so convenient.
Furthermore, there are equivalent bindings for mostly anything an
average iOS developer runs into in a normal application. RxCocoa has
bindings for UITabBar
’s selectedItem
. For
UIProgressView
’s progress
. For UITextField
’s
text. The list goes on and on and on.
Let’s Join a [RxSwift]Community
RxCocoa can’t be all things to all people, though. However, the beauty of open-source is that others can join in, help, and share their code.
Enter RxSwiftCommunity.
RxSwiftCommunity is, naturally, a community-led project to extend RxSwift
and RxCocoa to cover what those projects do not. A phenomenal example of
this, that I’ve used in Vignette, is RxGesture. RxGesture
exposes many gesture-based events by way of Observable
s. For example:
let someView = UIView()
let observable: Observable<UITapGestureRecognizer> =
someView.rx.tapGesture { (recognizer, _) in
recognizer.numberOfTapsRequired = 3
}
.when(.recognized)
Just like before, it’s certainly possible to do this by hand, but it is so much nicer to be able to just grab an open-source solution to do it for you. An open-source solution that has been used many many times, and thus is far better tested than any bespoke solution would be.
Furthermore, there are a ton of RxSwiftCommunity projects. To call out just a few:
- RxDataSources
A personal favorite of mine, which makes usingUITableView
andUICollectionView
incredibly easy - RxRealm
- RxMKMapView
Finally, newest and perhaps most interestingly:
- RxCombine
Currently empty, but perhaps an attempt at an RxSwift ↔ Combine bridge?
Speaking of Testing
Another incredible feature of RxSwift, and peer to RxCocoa, is RxTest.
RxTest is a wonderful suite of tools that allows you to easily test
code based on Observable
s. This includes simulating events on a stream,
at precise virtual times, in order to observe their results on the system.
I cover a lot of RxTest in my fifth and final RxSwift Primer post. Suffice it to say, RxTest makes it [almost] enjoyable to write unit tests for RxSwift-based code.
All Together Now
RxSwift in and of itself is impressive, but it is an empty sandwich. While it may be made of the most delicious bread known to man, it’s still just bread. Without the meat that is RxCocoa, the cheese that is RxCommunity, and the condiments that are RxTest, it’s just not the same.
Next week, I’ll spend some time comparing the API surface area of Combine to that of RxSwift, as well as discuss some core differences in the design of the two projects.