はじめに
最近流行りのリアクティブプログラミング。ReactKit やBondなどある中、ようやく老舗であるReactiveCocoaの仕様が固まりそうです。まだmasterリポジトリにはマージされていませんが、ひっそりとプレリリースされています。
試すには
Carthageからインストールするのが簡単でオススメです。ただし、Swift1.2対応のためxcode-selectにより使用するxcodebuildを変更してやる必要があります。
参考) CarthageでSwift 1.2に対応したライブラリをビルド
また、試すのであればswift-developmentブランチが最新であり良いと思います。Cartfileにgithub "ReactiveCocoa/ReactiveCocoa" "swift-development"のように書き、carthage updateでOK。Mac用が必要なければ別途--platform iOSも追記してください。
Signal/Producer
簡単な例として、「UITextFieldに文字が入力されていたらボタンを有効にする」というのをRAC3.0使って書いてみます。
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var button: UIButton!
lazy var dynamicProperty: DynamicProperty! = DynamicProperty(object: self.button, keyPath: "enabled")
override func viewDidLoad() {
super.viewDidLoad()
dynamicProperty <~ textField.rac_textSignal().toSignalProducer()
|> catch{ error in
return SignalProducer<AnyObject?, NoError>(value: "")
}
|> map{ value in
let str = value as! NSString
let can: Bool = str.length > 0
return can as AnyObject?
}
}
見ての通り、若干コード量が多く回りくどい印象があります。
ReactiveCocoa を Swift から使ってみた(2) KVO編でおっしゃっているように、rac_valuesForKeyPath()を使う事でKVOできるようになります。それを実現するため提供されているのがDynamicPropertyと<~です。<~は左辺に変更したいオブジェクトを配置し、右辺に変更起因となるシグナルを配置します。この例では右辺にSignalProducer<T, NSError>を配置しています。つまり、SignalProducer<T, NSError>からシグナルが発動するとそれがDynamicProperty (object.keyPath)に変更を加えるという流れです。
ちなみにSignalProducerはRACSignal (cold signal)に相当し、SignalがRACSignal (hot signal)に相当します。
また、気づいた方いらっしゃるかもしれませんが、ここではrac_textSignal()を使っています。これはobjective-Cで実装されたRACSignalを返す関数です。つまり、UIKitとやりとりを行う場合にはRACSignalを介す必要があります。
修正
●2015/3/22
コード中にcatchを追加しました。NSErrorをNoErrorにキャストすると同時にシグナルのエラーをキャッチしてます。(catchを挟まないとバインディングできないのも不思議な感じですが)
●2015/3/23
ikesyoさん指摘の通り、catch部修正しました
最後に
最初にも書きましたが、まだプレリリースです。仕様は変わるかもしれません。ご注意ください。