So recently I’ve got tired of writing massive nested callback blocks in Objective-C (like what they called “callback hell” in JS community), and I decided to give reactive programming in Cocoa a try.
To do this in Objective-C I looked into two frameworks: PromiseKit and ReactiveCocoa. I considered PromiseKit first since I’ve been familiar with the promise in js. For ReactiveCocoa, I’ve used OctoKit.objc before in my projects, and I’ve contributed a small method to it. When I read through their source code I was impressed by how they use AFNetworking in combo with ReactiveCocoa. This makes me want to try out ReactiveCocoa too.
Eventually I decided to go with ReactiveCocoa instead of PromiseKit, because PromiseKit has only 2 built-in Networking libraries: Alamofire and OMGHTTPURLRQ, but not AFNetworking that I heavily use. Of course you can write a bunch of categories yourself to make AFNetworking to work with PromiseKit, but that requires extra work. There are libraries on GitHub that do this for you (like this one recommended officially by PromiseKit), but I haven’t find a decent one that supports AFNetworking 3.
Also, as discussed here, PromiseKit provides only a small feature from reactive programming, while libraries like rxSwift/ReactiveCocoa are much purer ways to go reactive in iOS.
For example, with ReactiveCocoa, you can eliminate the use of delegates in most cases (they are still used behind the scenes, of course, but we write better and clearer code by replacing them with RACSignal in ReactiveObjC). Don’t get me wrong, I am not saying delegate pattern is bad. It’s good for complex structures like
UITableViewController where a huge number of delegate methods are provided in
UITableViewDataSouece. But for most cases where all a delegate method does is simply tells you when something is done, using block syntax or
ARCSignal in ReactiveCocoa are much better choices.
Here’s an example: in one of my projects, I used
CoreLocation and need the two delegate methods
CLLocationManagerDelegate. We can wrap these two delegate method into
RACSignal like so:
Then you can use them like this:
As you can see
RACSignal are much cleaner to handle that delegate methods. Obviously this cannot be done in PromiseKit, so ReactiveObjC seems to be a better choice for me. In fact ReactiveCocoa has already wrapped many delegate methods in
UIKit for you. For example,
[aTextField rac_textSignal] returns a signal for the text in
aTextField whenever its text changes.
Also, for networking, you can use ReactiveCocoa with AFNetworking like this:
You may wonder why I chose ReactiveCocoa over rxSwift. Well yes both of them are reactive programming libraries for Cocoa, but ReactiveCocoa has a longer history and has been battle tested in the official GitHub client for mac. Also, ReactiveCocoa has a pure Objective-C version: ReactiveObjC, so I can use it in Objective-C projects without worrying about the future breaking changes in Swift would break it. For more comparison between ReactiveCocoa and rxSwift, you can read this post from Ray Wenderlich.