RxSwift ボタンのタップを検知してViewModelに処理してもらう


記事を書こうと思ったきっかけ

MVVM設計でボタンタップを

registerButton.rx.tap.subscribe(onNext: {
    viewModel.createUser()
}).disposed(by: disposeBag)

みたいに書いていたんですけどなんかこれってViewModelの責務なんじゃないのかなと思いモヤモヤするので調べてみました。

実装

ViewModelを以下のようにします。

protocol ViewPresentable {
    typealias Input = (
        buttonTapped: Driver<()>, ()
    )

    var input: ViewPresentable.Input { get }
}

class ViewModel: ViewPresentable {
    var input: ViewPresentable.Input


    private let bag = DisposeBag()

    init(input: ViewPresentable.Input) {
        self.input = input

        self.input.buttonTapped.drive(onNext: {
            print("tapped")
        }).disposed(by: bag)
    }
}

次にViewControllerです。

class ViewController: UIViewController {

    @IBOutlet weak var button: UIButton!
    private var viewModel: ViewPresentable!

    override func viewDidLoad() {
        super.viewDidLoad()
        viewModel = ViewModel(input: (
            buttonTapped: button.rx.tap.asDriver(), ()
        ))
    }


}

これでボタンをタップしてみると

tapped

できました。
ここで重要なのは
inputの

typealias Input = (
        buttonTapped: Driver<()>, ()
    )

viewModel = ViewModel(input: (
            buttonTapped: button.rx.tap.asDriver(), ()
        ))

ですね。

少し成長できた気分です。
UIの更新だけなら最初のやり方でもいいかもしれないですが、ビジネスロジックなども伴う時はこんな感じで書いた方がいいのかな?と思います。

指摘などありましたらよろしくお願いいたします。