Pebble Coding

プログラマーの作業メモ

RxSwift 超入門その2

let minimalUsernameLength = 5
let minimalPasswordLength = 5

class SimpleValidationViewController : ViewController {

    @IBOutlet weak var usernameOutlet: UITextField!
    @IBOutlet weak var usernameValidOutlet: UILabel!

    @IBOutlet weak var passwordOutlet: UITextField!
    @IBOutlet weak var passwordValidOutlet: UILabel!

    @IBOutlet weak var doSomethingOutlet: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        // 初期状態で表示するワーニングメッセージ
        usernameValidOutlet.text = "Username has to be at least \(minimalUsernameLength) characters"
        // 初期状態で表示するワーニングメッセージ
        passwordValidOutlet.text = "Password has to be at least \(minimalPasswordLength) characters"

        // ユーザー名が有効かどうか
        let usernameValid = usernameOutlet.rx.text.orEmpty
            .map { $0.characters.count >= minimalUsernameLength }
            .shareReplay(1)

        // パスワードが有効かどうか
        let passwordValid = passwordOutlet.rx.text.orEmpty
            .map { $0.characters.count >= minimalPasswordLength }
            .shareReplay(1)

        // ユーザー名とパスワードがともに有効かどうか
        let everythingValid = Observable.combineLatest(usernameValid, passwordValid) { $0 && $1 }
            .shareReplay(1)

        // ユーザー名が有効になったらパスワード入力欄をenabledにする。その逆も行う。
        usernameValid
            .bindTo(passwordOutlet.rx.isEnabled)
            .disposed(by: disposeBag)

        // ユーザー名が有効になったらユーザー名不備メッセージを隠す。その逆も行う。
        usernameValid
            .bindTo(usernameValidOutlet.rx.isHidden)
            .disposed(by: disposeBag)

        // パスワードが有効になったらパスワード不備メッセージを隠す。その逆も行う。
        passwordValid
            .bindTo(passwordValidOutlet.rx.isHidden)
            .disposed(by: disposeBag)

        // ユーザー名、パスワードがともに有効になったらボタンを有効にする。その逆も行う。
        everythingValid
            .bindTo(doSomethingOutlet.rx.isEnabled)
            .disposed(by: disposeBag)

        // ボタンがタップされた時の処理
        doSomethingOutlet.rx.tap
            .subscribe(onNext: { [weak self] in self?.showAlert() })
            .disposed(by: disposeBag)
    }

    func showAlert() {
        let alertView = UIAlertView(
            title: "RxExample",
            message: "This is wonderful",
            delegate: nil,
            cancelButtonTitle: "OK"
        )

        alertView.show()
    }

}

このサンプルから学習できることは、.sharePlay(1)です。
これは無駄に同じ処理が複数回走るのを防ぐためのメソッドと考えて良いです。