こんにちは。きんくまです。
前回に引き続き、Functional Reactive Programming = FRP のライブラリを試してみました。
今回はiOSのライブラリのReactiveCocoaです。
>> ReactiveCocoa/ReactiveCocoa · GitHub
RactiveCocoaはreadmeによると、Microsoftの.NetのReactive Extensions (Rx)を元に作られています。
で、良いチュートリアルがあったので、今回はそれをObjective-Cではなくswiftでやってみました。
>> ReactiveCocoa Tutorial – The Definitive Introduction: Part 1/2 (by Colin Eberhardt)
ただ、swiftでやっていたところ、所々わからないところがあり、さらに検索してみたところ既に同じことをやられている方がいました。かなり助けられました。
>> A SWIFT REACTION (by Yusef Napora)
どんなデモアプリ?
名前の入力欄があり、サインインボタンはまだ押すことはできません。
入力文字数が3文字を越えるとテキストフィールドの背景が白になります。
また、名前と名字の両方ともがそうなると、サインインボタンが押せるようになります。
ボタンを押すと、ダミーの非同期処理の照会が走って
うまくいくと、次の画面にすすみます。オリジナルのチュートリアルでは猫ちゃんだったのですが、ここでは文字を表示しています。
ソースコード
import UIKit class ViewController: UIViewController { @IBOutlet weak var usernameTextFieid:UITextField! @IBOutlet weak var passwordTextFieid:UITextField! @IBOutlet weak var signInButton:UIButton! @IBOutlet weak var loadingIndicator:UIActivityIndicatorView! @IBOutlet weak var errorLabel:UILabel! var signInService:RWDummySignInService! override func viewDidLoad() { super.viewDidLoad() self.signInService = RWDummySignInService() self.errorLabel.hidden = true self.loadingIndicator.hidden = true let validUsernameSignal:RACSignal = self.usernameTextFieid.rac_textSignal() .map { (value:AnyObject!) -> AnyObject! in return self.isValidnUsername(value as NSString) } let validPasswordSignal:RACSignal = self.passwordTextFieid.rac_textSignal() .map { (value:AnyObject!) -> AnyObject! in return self.isValidPassword(value as NSString) } validUsernameSignal .map { (value:AnyObject!) -> AnyObject! in return (value as NSNumber).boolValue ? UIColor.clearColor() : UIColor.yellowColor() } .subscribeNext { (value:AnyObject!) -> Void in self.usernameTextFieid.backgroundColor = (value as UIColor) } validPasswordSignal .map { (value:AnyObject!) -> AnyObject! in (value as NSNumber).boolValue ? UIColor.clearColor() : UIColor.yellowColor() } .subscribeNext { (value:AnyObject!) -> Void in self.passwordTextFieid.backgroundColor = (value as UIColor) } let signUpActiveSignal:RACSignal = RACSignal .combineLatest([validUsernameSignal, validPasswordSignal]) .and() signUpActiveSignal.subscribeNext { (value:AnyObject!) -> Void in self.signInButton.enabled = (value as NSNumber).boolValue } self.signInButton.rac_signalForControlEvents(UIControlEvents.TouchUpInside) .doNext { (x:AnyObject!) -> Void in self.signInButton.enabled = false self.errorLabel.hidden = true self.loadingIndicator.hidden = false self.loadingIndicator.startAnimating() } .flattenMap { (x:AnyObject!) -> RACStream! in return self.signInSignal() } .subscribeNext { (value:AnyObject!) -> Void in self.loadingIndicator.stopAnimating() let success = (value as NSNumber).boolValue if(success){ self.performSegueWithIdentifier("signInSuccess", sender: self) }else{ self.errorLabel.hidden = false } self.signInButton.enabled = true self.loadingIndicator.hidden = true } } private func isValidnUsername(username:NSString) -> NSNumber{ return NSNumber(bool:(username.length > 3)) } private func isValidPassword(password:NSString) -> NSNumber{ return NSNumber(bool:(password.length > 3)) } override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { usernameTextFieid.resignFirstResponder() passwordTextFieid.resignFirstResponder() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } func signInSignal()->RACSignal{ return RACSignal.createSignal{ (subscriber:RACSubscriber!) -> RACDisposable! in self.signInService.signInWithUsername(self.usernameTextFieid.text, password: self.passwordTextFieid.text, complete: { (success:Bool) -> Void in subscriber.sendNext(NSNumber(bool:success)) subscriber.sendCompleted() }) return nil } } }
上のプロジェクトではCocoaPodsは使わず手動でライブラリを入れてあります。
感想
書いてみた感じでは、前回のbacon.jsと同様 データの流れがあって、それの値を読み取ったり、流れを合流させたりといった感じ。たぶんこの感じがFRPなんだと思われ。
あとObjective-Cのコードだと、 [ ] = square braket がやたらと入れ子になっていて見づらいのですが、swiftだとそれがないので見やすい&書きやすいと思いました。
ちょっと気をつけたいことは、
・最新版のライブラリがiOS8以降対応(iOS7だとダメ)
・開発中のバージョン3.0ではいろいろと代わりそう
ということでしょうか。
■ 自作iPhoneアプリ 好評発売中!
・フォルメモ - シンプルなフォルダつきメモ帳
・ジッピー電卓 - 消費税や割引もサクサク計算!
■ LINEスタンプ作りました!
毎日使える。とぼけたウサギ