will and way

ただの自分用メモを人に伝える形式で書くことでわかりやすくまとめてるはずのブログ

UITableViewCellの中身をRxで監視するときのtips

シナリオ

  1. テキスト入力をもつTableViewCellがある
  2. 画面には更新ボタンがあり、押した時に、キーボードを閉じたい

結論ソース

※諸々省略してます

// UITableViewCellにcellForRowAtIndexまでにunbindさせるための情報を定義する
extension Reactive where Base: UITableViewCell {
    var prepairForReuse: Observable<Void> {
        return methodInvoked(#selector(base.prepareForReuse))
            .map { _ -> Void in
                return Void()
        }
    }

    var obsolete: Observable<Void> {
        return Observable.merge(prepairForReuse, deallocated)
    }
}


extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as TextCell
        weak var weakCell = cell

        updateButton.rx.tap
            .takeUntil(cell.rx.obsolete)
            .subscribe(onNext: { [weak self] _ in
                weakCell?.closeKeyboard()
            })
            .disposed(by: disposeBag)
    }
}

sentMessageでprepairForReuseを監視

prepairForResuseとdeallocのどちらかのイベントを受け取るまで監視しておけば良いので、それらをまとめてobsoleteというイベントを生やしました。

これをしないと、tableViewをスクロールするたびにsubscribeが増えるので予期せぬ動作を引き起こす可能性がある。