Taming Callbacks in iOS: Bolts Framework
17 Dec 2014Managing many asynchronous events in iOS can get hairy, but it’s a fact of life when working with remote services. So how do we avoid callback hell?
Promises.
Below I’ll explain why I chose the Bolts Framework (BF) over PromiseKit and ReactiveCocoa.
A naive way to handle asynchronous code in Swift is with standard blocks. Let’s say we need to change the orientation of a video, save a thumbnail, and then save the video for a post. We could end up with something like this:
Here’s the callback pyramid of doom. If you’re unfamiliar with this, you can read more about it here (article is on javascript, but concept still applies).
We don’t want this, and promises are the way to fix it. But which framework should we use?
Reactive Cocoa?
- Based on the principals of Functional Reactive Programming.
- Required one to wrap everything with RAC types.
- Focused on handling streams, not my primary use case.
- When all I need are promises, RAC was too heavy and obtrusive for my tastes.
PromiseKit?
- Inspired by Bolts.
- Separate library for Objective C and Swift, so it can take advantage of Swift generics.
- Comes with Objective C categories for many built in iOS types, like NSURLConnection.
- At the time of this writing, it does not have a pod for the Swift library because of CocoaPod’s limitations.
- Not straightforward when switching between Objective C and Swift.
Bolts Framework’s BFTask? Yes.
- The simplest of the three.
- Works seamlessly across Objective C and Swift.
- Does not support Swift generics which can lead to some verbosity.
- Supported natively by the Parse Framework, which is what I’m using.
I actually started with PromiseKit and just went to Bolts because I found it the simplest of the three. At first, I was all about the Swift support, but found myself going back and forth between Obj C and Swift, making Bolts a better match. As CocoaPods and Swift matures, I will definitely take another glance at PromiseKit. Right now, I’m extremely happy with BFTask:
And better error handling code because in true promise fashion, the caller can receive the error at the end regardless of where it happens:
Takeaway
- Smash your iOS pyramids of doom with Bolts or PromiseKit.
- Handle to streams of potentially infinite data with ReactiveCocoa.
- See the source code for all these samples here