タイトル通りタッチエンドからちょっと経ったらなにか処理をする+その間に次のタッチをされたらキャンセル、みたいなことをRx(Swift)でやりたかったが、UniRxからRxに入門した口なのでちょっと手間取った。
TL;DR. Observableを返すObservableに対してswitchLatestを使うとよい
実装
単にタッチエンドから一定時間経ったら、ということだったら普通にdebounceを使えばいいんだけど、その間に再びタッチされた場合にはキャンセルして、次のタッチエンドまでなにも流さないようにしたかった。
UniRxではRepeatとかを使っていたので(参考:「未来のプログラミング技術をUnityで -UniRx-」の例)、同じようにストリームが終了した時にまた最初からやり直すメソッドがあると思ったんだけど、Rxのrepeatは全然別の処理だった。
retryはエラー時にやり直すメソッドなのでまたちょっと違う。
でどうやるのか調べていたんだけど、結局全然違う方法を使う必要があって、Observableを入れ子にして最新のものだけを使用するというswitchLatestがそれだった。
let TOUCH_END_DURATION = 0.5 |
strokeSettledが望みのストリームで、タッチ開始ごと(resetTouchSubject)に新しいObservable(touchEndedSubject)を流すストリームに対して、switchLatestで一番新しいObservableだけを対象にするtouchEndedSubjectのタッチエンドをdebounceでフィルタして流すことで、タッチから一定時間が経った時にイベントが流れる- タッチ開始ごとに
switchLatestで古いタッチエンドのObservableが破棄され新しい物に切り替えられるので、タッチエンドからすぐ次のタッチを開始した場合にはstrokeSettledにはイベントは流れない
参考
- Intro to Rx - Combining sequencesにライブサーチの例が載っている。
Mergeだとサーチ結果が混じってしまう危険性があるけど、Switchなら解決、と。