Choosing a Swift reactive programming library
We are currently working on a new project for Tate. While discussing the architecture for the app, we noticed some features would benefit from functional reactive programming (FRP). Some of us have experience with FRP in other languages, but not yet with Swift. Currently there are 2 major libraries available: RxSwift and ReactiveCocoa (RAC). So which one should we use?
First off, I searched the web for opinions about both libraries. Most of what I found was perfectly summarized by Ash Furrow in his blog ReactiveCocoa vs RxSwift: “if you’re a beginner, it really doesn’t matter […] Try one framework, then try the other. See for yourself which one you prefer! Then you can figure out why you prefer it.”
So I did. First I took RxSwift for a spin. After that I tried ReactiveCocoa. Note that I’m a beginner in FRP and I only used both libraries for a day or so, but I immediately noticed things I found intuitive and liked. This is what I noticed from playing around with both:
RxSwift supports CocoaPods and Carthage. RAC has Carthage support and an unofficial pod. It’s up to date and works, but it feels a bit stupid they don’t support pods officially. So both are easy to get started.
RxSwift follows ReactiveX conventions. That makes it easy to discover names of operators in the docs and even to read blogs about RxJava since they use the same terminology. ReactiveCocoa uses slightly different names for operators and a lot of other things, which made it a little harder for me to get started and discover what the method you need is called. Documentation for RAC is there, but not as much as there is for the ReactiveX style libraries.
RxSwift is pretty new and has no legacy. It feels stable and complete. RAC is from the Objective-C era. RAC3 and up have very good Swift support. But I stumble into Objective-C blogs and code a lot that doesn’t match the current state of RAC. There is an active community for RAC though, so most of the time there also is an up to date answer to your question somewhere.
RxSwift has untyped errors in observables. While playing with RxSwift I immediately missed the error types I was used to from promisses. RAC does have typed errors, so that really is something that makes me like RAC a little more than RxSwift.
When using RxJava,one of the first mistakes I made was firing a cold (networking) observable way too often by subscribing multiple times. RAC tries to solve this by having 2 different types for hot and cold observables. RxSwift has just one type for both, like most FRP libraries have. I think I like the RAC approach better, though I’ll have to use it a bit more to see if that opinion holds up in a larger code base.
Mainly based on these experiences, I decided to go with RAC for now. It’s somewhat harder to find documentation and posts that answer my questions, but I feel the error types and separation of hot/cold observables are bigger wins.
Does that mean you should choose RAC for your project? No, I think Ash Furrow was correct, you really should give both a try. Even if it’s only one day of fiddling around, it gives you much more of a feeling of what fits your use case.
I’m curious what we will learn about FRP in this project and how it will influence our opinion about these libraries!
Check out our Engineering Blog for more in depth stories about pragmatic code for happy users!