The Official Venmo Blog

May 20, 2014 · by Ben Guo

By Ben Guo

We've recently started using ReactiveCocoa in the Venmo iOS app, and we've found that it provides an expressive, unified alternative to patterns like callback blocks, delegate methods, target-action, notifications, and KVO. If you haven't heard of ReactiveCocoa or Functional Reactive Programming (FRP), we recommend starting with this awesome post by Josh Abernathy and the official introduction. In this post, we'll walk through implementing a simple reactive user interface, with and without ReactiveCocoa. Hopefully, we'll inspire you to start experimenting with FRP on your own!

We'll be working on a simple signup form that looks like this:

Let's start with the top of the form, where the user can add or change their profile photo.

The photoButton's text should be either "Add photo" or "Change photo", depending on whether or not a photo has been added, and the imageView's image should be the currently chosen photo. Here's a reasonable imperative implementation:

Imperative programming involves describing how to do something. Reactive programming, on the other hand, involves describing what something is, using streams of values. Here's an equivalent implementation, with ReactiveCocoa.

Our reactive code is more linear than our imperative code, but also arguably more difficult to parse. It's hard to see the value of reactive programming at this level of complexity, but as we add more functionality, we'll begin to see the benefits of choosing ReactiveCocoa.

To finish our form, we'll need a username field, a password field, and a submit button. The submit button should only be enabled when we've added a photo and entered a username and password. For some extra reactivity, let's make each text field's text turn orange while editing.

Dealing with state is messy in the imperative world. Our code has become rather difficult to understand — we update the submit button in three different places, setPhoto: has three side effects, and in general, things seem to be happening all over the place. Also, notice that modifying our imperative implementation required touching nearly everything we'd written in (1a). Adding functionality usually means adding new events and states. In the imperative world, we have to respond to discrete events and state changes and make sure everything stays up to date, resulting in less linear, more tightly coupled code that's more difficult to understand and update.

Updating our reactive implementation hardly required any changes to what we wrote in (1b), and the resulting code is much more linear. Because state changes propagate automatically, we can define the flow of state rather than responding to discrete events. Even in this simple example, reactive programming has empowered us to write code that's easier to understand and maintain.

We've only scratched the surface of ReactiveCocoa, but hopefully we've given you a more concrete sense of the power of reactive programming. So go forth, compose signals, minimize state, and put away that spaghetti — let's make lasagna ;)

If you're interested, you can check out the complete example project here.