【RxSwift】TextField で .editingChanged の時だけ文字列を取得したい
RxSwift
で TextField.text
の変更をリッスンしたい時、下記のように書こうとした経験がある人は結構多いかと思います👀
textField.rx.text .subscribe(onNext: { text in print(text) }) .disposed(by: disposeBag)
あまり RxSwift
に馴染みのない場合、これでも取得できるんじゃないの?と一瞬思うかもしれませんが、上記の例だと .editingChanged
以外の TextField
イベントもストリームに流れてきます。
「どのイベントでもいいからとりあえず TextField
の変更をリッスンしたい」というユースケースではこのままでもいいかもしれませんが 、テキストの変更を受け取って API
にリクエストするなどの状況で使うとなると、不要なイベントがストリームに流れてきてしまうため API
のリクエストが意図せず増えてしまう可能性があります。
ちなみに、textField.rx.text
がどんな時にイベントを流すかは下記の記事でわかりやすく載っていますので、ぜひ参考にしてみてください。
結論
結論、下記のようにすることで文字列に変更があった場合(.editingChanged
) にのみイベントを流すことができます。
textField.rx.controlEvent(.editingChanged) .compactMap {[unowned self] in textField.text } .distinctUntilChanged() .subscribe(onNext: { text in print(text) }) .disposed(by: disposeBag)
textField.rx.controlEvent(.editingChanged)
で TextField
の .editingChanged
イベントを受け取り、そのイベントを元に TextField.text
+ compactMap
でアンラップした文字列をストリームに流します。また、今回はテキストに変更がなかった場合(同じ文字列を取得した場合)は、イベントを流したくなかったので .distinctUntilChanged()
で text
をフィルターしています。
ちなみに、compactMap()
オペレーターは RxSwift 5.0.0
以降でしか使用できないのでご注意を!
という感じで本日も以上になります👋