Strongly typed actions in ReactiveCocoa 5

First alpha of RAC5 was released a couple of days ago and it got me really excited. Especially the release notes. In the upcoming few articles I will try to lay out what's new in version 5 since version 4.

First up - strongly typed CocoaAction. I wrote before that you use CocoaAction instances to hook up Action's to Cocoa[Touch] controls. However one caveat that this approach had was that CocoaAction instances passed in AnyObject as a control that triggered said action. In version 5 that has changed. RAC now has strongly typed CocoaAction and let me show you how it works.

The way RAC achieves strongly typed actions is quite simple: generics. The class' signature changed from simple

public final class CocoaAction: NSObject {  

to

public final class CocoaAction<Sender>: NSObject {  

where Sender is a type of UIControl or NSControl subclass. To be fair though, Sender is not constrained (at least in base class), so it's not necessary for the type to be subclass (or instance) of UIControl or NSControl.

A refresher from my previous post:

Create an action that saves given parameter into user defaults (now in swift 3!):

let action = Action<Bool, Void, NoError> { value in  
    return SignalProducer<Void, NoError> { observer, _ in
        let defaults = UserDefaults.standard
        defaults.set(value, forKey: Settings.VibrateKey)
        defaults.synchronize()
        observer.sendCompleted()
    }
}

Now that we have action, setting up the CocoaAction is just as easy with one additional step - provide the class of the UIControl which will trigger the defined action. The usage of CocoaAction becomes a bit tidier since the casting is done by the framework itself:

let switchAction = CocoaAction<UISwitch>(action, { switch in  
    return switch.isOn // no more type casting!
}

And hooking up the action to the UISwitch control is just the same:

switch.addTarget(self, action: CocoaAction.selector, for: .valueChanged)  

This is the first quick post in series about ReactiveCocoa 5 and Swift 3.