If the title doesn't sound familiar to you, ReactiveCocoa is an FRP* inspired framework, counting remarkable usage in the Cocoa world. It's not just trending because it's fancy to try reactive programming, but there are several companies out there using it in production. Now with Swift coming into the picture, it has been rewarded with a brand new version, 3.0. If you are interested in some clarification on ReactiveCocoa 3.0, I suggest to read the framework documentation and the changelog in advance. If you are interested in how I upgraded my iOS app from ReactiveCocoa 2.4 to 3.0, just read on.
Because I've been using ReactiveCocoa 2 with Objective-C for almost a year now and I'm very excited to see what its creators considered important to change in the concept, how they leverage the benefits of the Swift language and how it feels to use the new framework.
I'm interested in how reactive programming (or #howcanicallit) evolves, especially in the world of Cocoa.
Swift is at our doorstep. We will use it, eventually.
The examples are from a project..
..which is the iOS app of the brewfactory family. You can find the whole source of BrewMobile on GitHub. It's close to my heart, because I really like the taste of the IPAs these guys brew with their home brewing machine. I've already shared some experiences about how to go MVVM & reactive with Swift using ReactiveCocoa 2.4 back then, with the very same project. Now is the time to make it RAC3ified.
See @kutpet testing the reactive IPA enthusiastically.
I thought I would struggle for a day to make the project RAC 3 compatible, then it happened in two minutes. I've updated my
Cartfile and shot an
update. The project built & ran and worked like before. I was able to upgrade the whole project using RAC 2 and 3 at the same time, reducing the old parts step by step like a tutorial.
I started with transforming the composition of my HTTP requests, that felt pretty smooth.
rac_dataWithRequest gives you a
SignalProducer back which you can apply operators on, like
filter, or add any side effects with
Next I wanted to turn my
RACCommands into Actions and CocoaActions. At first sight,
Action might seem identical to
RACCommand, but it's useful for a lot more. To make it work with
UIKit elements though, you have to add
CocoaAction to the picture.
Let's see the above created network request inside an
Now, how to trigger it by a button press for example? Check out the view model for the connected
As you can see, it's possible to pass an input value with it. Although the input (and output) type has to be defined with the original
The view controller with the
That's it! You can press the button and start brewing. Of course, if your HTTP request failed, you should get notified about it:
observeOn(UIScheduler()) is necessary, because unlike RACCommand, Actions are not bound to the main thread by default.
Instead of all the
RAC macros, now you can make your properties a
MutableProperty. With the
<~ operator, you are able to bind a
SignalProducer, or another property to a given property.
The cool thing is, its value is mutable but you are still able to define it as a constant. Mutable properties' producers come handy when you would like to operate on the observed values.
Let me know if you found the good old
and operator which I apparently didn't.
There are a lot of examples in the project, using
MutableProperty, I even updated my model's states with it. There is only one catch, which is about observing
UIKit elements, so read on.
They are not here yet, but it is possible to build upon the Objective-C bridging.
RACSignal has a new method
toSignalProducer() which subscribes to the given signal for every
It also means you are able to add side effects for example to the returned
And that's it.
catchis a reserved word in Swift 2, it will become
flatMapErrorin the future.
The hard parts
As someone coming from Objective-C and ReactiveCocoa 2, I have to admit it was not easy to upgrade my project. Given it is brand new, we are not full of examples out there. With this post, I tried to give you some. What I suggest is to read a lot of tests and search the issues. They are not just up to date, but the contributors always answer the questions with suggestions and clear explanation, very useful, many thanks!
You might have the natural feeling, that the framework is a bit raw now and there is also some confusion out there which might alter the framework later, after the community starts using and help shaping it. The point is to start somewhere, hope this project will help you.
Swift 1.2 or 2.0?
The project (and this post) is currently Swift 1.2 compatible, but check out my new article about using Swift 2.0 and ReactiveCocoa 4.0, if you're interested in that setup.
I think ReactiveCocoa is a well-designed, mature system, people are building up big software with it, like GitHub for Mac, SoundCloud, etc., which is amazing. Although for beginners it might be hard to understand, given its complexity. I also understand that the contributors have a lot to carry on their shoulders with the Objective-C codebase.
That's why it is a different story today, to come up with ideas based on the similar inspiration, but starting from zero, with Swift.
People who already use ReactiveCocoa in Objective-C will have a safe option to upgrade to Swift with ReactiveCocoa 3. I will definitely keep my eyes open though, there are promising projects out there.
*About FRP, Rx and sensitive definitions
I'm just a user of this framework, so I'm actually not concerned about ReactiveCocoa not being an official reactive extension and not conforming to a definition it should, to call it FRP. From my point of view, it is operating with streams and it is using functional operators on streams, so it makes my life easier. Now with Swift and the new concepts (e.g. separate hot and cold observables) it's actually even closer to the Rx ports, with some differences. FRP or not, ReactiveCocoa's design had been influenced by great theories combined with all the great people's ideas who's working on it, admirable anyway.
Useful readings in the topic
- Weekly Swift resources by @NatashaTheRobot
- Erica Sadun's blog
- Airspeed Velocity
- Swift Sandbox newsletter