UITextFieldとUILabelをRxSwiftでバインディングする方法
概要
タイトルで「バインディング」という言葉を使いました。 しかしRxSwift初心者にとってまたiOS開発者にとって一番勘違いを起こしてしまうのがこの「バインディング」だと思ってます。 バインディングと格好良く行っていますが要するにSwiftのクロージャーの中で処理を繋げることと同じだと思っています。
今回はそれをUITextFieldとUILabelとの接続を通して理解を深めたいと思います。
開発環境について
Xcode: 10.1
Swift: 4.2
RxSwift: 4.4.0
RxCocoa: 4.4.0
バインディング
前回はUITextFieldのRxSwiftで他の@IBOutletと連携させない単独の処理を説明しました。 今回はUILabelと連携する方法についてです。
storyboardの内容は以前と変わりません。
ViewControlleの編集を行います。
import UIKit import RxCocoa import RxSwift class ViewController: UIViewController { @IBOutlet weak var button: UIButton! @IBOutlet weak var label: UILabel! @IBOutlet weak var textField: UITextField! var disposeBag = DisposeBag() var count = 0 override func viewDidLoad() { super.viewDidLoad() textField.rx.text.orEmpty.asDriver() .drive(onNext: { [unowned self] text in // 入力するたびにこの処理が走る print("text: \(text)") print("isEditing: \(self.textField.isEditing)") // self.textField.isEditing はBool self.label.text = text }) .disposed(by: disposeBag) textField.rx.text .bind(to: label.rx.text) // .bind の部分が .drive と同じです .disposed(by: disposeBag) } }
上で2つ同じ処理をしているコードがあります。
vc.swift
textField.rx.text.orEmpty.asDriver() .drive(onNext: { [unowned self] text in // 入力するたびにこの処理が走る print("text: \(text)") print("isEditing: \(self.textField.isEditing)") // self.textField.isEditing はBool self.label.text = text }) .disposed(by: disposeBag)
と
textField.rx.text .bind(to: label.rx.text) // .bind の部分が .drive と同じです .disposed(by: disposeBag)
この部分です。
僕にとっては同じ処理なのに2つの異なる書き方がある時点で勘違いが起きてしまう理由になりそうですが、
このように書くことができてしまいます。
.bind
はどちらかというとRxを使ったAndroidに近い書き方かなという印象です。
APIから取得してごちゃごちゃとしたい場合は上の.drive(onNext: { [unowned self] text in
なのかなと思います。
逆に言えば、 上記の2つの書き方のどちらかでUITextFieldとUILabelを連携できるようになるということでそれはそれで便利ではあります。