ReactiveCocoa is a library created by GitHub that brings “Functional Reactive Programming” to Objective-C. It provides a number useful features right out of the gate which gives a developer the power to observe, transform, merge, and filter signals that contain values.
More importantly, it has the power to build on top of and replace existing (and sometimes archaic) patterns used in Objective-C. One of the most common of these patterns is the “delegate pattern.”
The Delegate Pattern
The delegate pattern is a pattern of delegating tasks to an object and potentially informing it of certain actions that are being taken. Here’s a typical example of the delegate pattern found in iOS programming:
In this particular example, the object (presumably a UIViewController) is the delegate to both the
UISearchDisplayController. The searchBar:textDidChange: delegate method updates the search results and the UISearchDisplayController delegate methods (searchDisplayControllerDidBeginSearch and searchDisplayControllerDidEndSearch respectively) track whether the search is currently active.
There are a couple of issues with this delegate approach:
- There is only ever one object that can subscribe to changes to the
UISearchDisplayController. All actions must go through the delegate.
- The act of searching is is scattered across three different callbacks.
The ReactiveCocoa Toolbox
ReactiveCocoa has built-in helpers for creating signals from any
selector on an object or protocol.
rac_signalForSelector: and rac_signalForSelector:fromProtocol:
These two helpers will create a signal that is bound to a selector, such that any time that selector is invoked on the object it will send a new value through the signal.
This helper will “lift” a selector into “signal space” where the selector is invoked anytime the corresponding argument signals send a new value. The signals passed to the
rac_liftSelector must match the number of arguments expressed by the selector.
Replacing the Delegate Pattern
Now that we have familiarized ourselves with some of the more powerful aspects of ReactiveCocoa, we can replace the delegate pattern example with one that uses signals.
Instead of having to assign a delegate to the UISearchBar and implement
searchBar:textDidChange:, let’s modify the UISearchBar so there is a signal representing changes to the text.
A new method had been added to UISearchBar (via Objective-C categories) that creates a signal from the selector
searchBar:textDidChange: and maps the signal so that it only ever sends the text.
In order to know whether the UISearchDisplayController is active or not, it requires that two delegate selectors are subscribed to:
The implementation above does the following:
- Creates a signal from
searchDisplayControllerDidBeginSearch:and maps it to
- Creates a signal from
searchDisplayControllerDidEndSearchand maps it to
- Merges the two signals via RACSignal’s
mergemethod where it sends the most recent signal value.
Bringing it All Together
We can now replace the delegate pattern example above with this:
The search results are updated when the search bar’s text changes, and the search is marked as active when the search display controller is active. Moreover, if another object wanted to subscribe for changes, it wouldn’t have to go through a delegate — it could simply subscribe to the signal.