Help us understand the problem. What is going on with this article?

RxSwiftで双方向データバインディング

More than 3 years have passed since last update.

 FunctionalReactiveProgramming(FRP)の勉強中です。
まだ正直なところ『なるほど,分からん』という状態ですが
RxSwiftをおっかなびっくり触ってみた結果を整理しようと思います。
(触ってみたら動いたレベルなので他に良い使い方があるかも......です)

1. RxSwiftとは?

 ReactiveX(Reactive Extension)という,FRPを実現するためのライブラリのSwift実装です。
Swift実装以外にもJavaScriptやJava,C#など様々な言語で実装されたライブラリがあるようです。
(AndroidだとRxAndroidとかあるみたいですね)

RxSwift

2. どんなことが出来るの?

 分かりやすいポイント(というか自分が現状で理解できた範囲では)
「データバインド」「Promiseパターン」を簡単に実現できるようになります。
アプリの実装レベルで言うと,画面描画処理が楽になる(データの変更がViewに伝搬する)ことと
コールバック地獄になりがちな非同期処理をスッキリ書けるようになることが恩恵ですね。
※今回はデータバインドだけについて書いてみます。

3. 導入するには?

 CocoaPods先生に頼りましょう。

Podfile
# Podfile
use_frameworks!
pod 'RxSwift', '~> 2.0.0-beta'
pod 'RxCocoa', '~> 2.0.0-beta'
pod 'RxBlocking', '~> 2.0.0-beta'

 pod installで上記3つのライブラリが導入されます。

4. 単方向バインディングをやってみる

 UITextField→ViewModelにバインドしてみます。

ViewController
import UIKit
import RxSwift
import RxCocoa
import RxBlocking

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!

    let viewModel = ViewModel()
    let bag       = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        bindViewAndModel()
    }

    /**
     データバインド設定
     */
    private func bindViewAndModel() {
        textField.rx_text.subscribeNext { [unowned self] text in
            self.viewModel.text = text
        }.addDisposableTo(bag)
    }   
} 

 UITextFieldが変わる度に,subscriveNextで渡したClosureが作動します。
結果,ViewModelの変数textが同期して更新される...といった形になります。

5. 双方向バインディングをやってみる

 今度は、UITextField←→ViewModelの双方向バインディングです。
ちょっと調べてみるとRxSwiftの中の人がこんなことを仰ってました。

two-way binding

Two way binding are just two unidirectional bindings :).

 ただの単方向バインディング2つを合わせりゃ双方向バインディングだよ,と。
一発で双方向バインドする方法はないから,交互にバインドするしかない……?
というわけで試してみました。

 今度はViewModel側からもBindするので,ちょっとViewModelを書き換えます。

ViewModel
import Foundation
import RxSwift

class ViewModel {

    var text:Variable<String> = Variable<String>("森伊蔵とキッコロ")

    init() {
        // 初期化
    }
}

 String型ではなく,RxSwiftが提供するVariable型で定義します。
Variable型を使うことで,バインド用の関数が使えるようになります。
で,ViewController側にもViewModel→ViewControllerのバインド設定を追加。

ViewController
    /**
     データバインド
     */
    private func bindViewAndModel() {
        textField.rx_text.subscribeNext { [unowned self] text in
            self.viewModel.text.value = text
        }.addDisposableTo(bag)
        viewModel.text.bindTo(textField.rx_text).addDisposableTo(bag)
    }
}

 ViewModel→UITextFieldへのバインドは,bindTo関数だと上手くいくようです。
コードからViewModelの値を変えてあげると連動してUITextFieldの値も更新されます。

cross-xross
はんなり京都系エンジニア
http://niwaka.hateblo.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした