タイトル通りタッチエンドからちょっと経ったらなにか処理をする+その間に次のタッチをされたらキャンセル、みたいなことを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
なら解決、と。