はじめに
最近流行りのリアクティブプログラミング。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
部修正しました
最後に
最初にも書きましたが、まだプレリリースです。仕様は変わるかもしれません。ご注意ください。