メッセージが届くたびにビープ音を鳴らすインスタントメッセージングアプリがあるとします。ビープ音をdebounce
したいのですが、次のメッセージではなく、最初のメッセージが到着したときのビープ音を再生します(たとえば、2秒の時間内)。
別の例は次のとおりです。私のアプリは入力通知を送信します(そのため、チャットしているユーザーは、メッセージを入力していることがわかります)。入力を開始したときに入力通知を送信したいのですが、新しい通知はX秒間隔でのみ送信するため、入力するすべての文字に対して入力通知を送信しません。
これは理にかなっていますか?そのためのオペレーターはいますか?既存のオペレーターでそれを達成できますか?
これは最初の例の私のコードです。今はdebounce
で解決していますが、理想的ではありません。 1秒間隔で1000個のメッセージを受信した場合、最後のメッセージが到着するまでサウンドは再生されません(最初のメッセージでサウンドを再生したい)。
self.messagesHandler.messages
.asObservable()
.skip(1)
.debounce(2, scheduler: MainScheduler.instance)
.subscribeNext { [weak self] message in
self?.playMessageArrivedSound()
}.addDisposableTo(self.disposeBag)
ありがとう!
RxSwift 3用に更新され、throttle
演算子が改善されました
RxSwift 3.0.0-beta.1で導入されたthrotlle
演算子の新しい動作により、次のように使用できます。
downloadButton.rx.tap
.throttle(3, latest: false, scheduler: MainScheduler.instance)
.subscribe(onNext: { _ in
NSLog("tap")
}).addDisposableTo(bag)
回答の古いバージョン
window
演算子を使用してから、Observable
を使用してObservable<Observable<Type>>
をフラットflatMap
に変換します。
このサンプルコードは、3秒ごとのウィンドウの最初のタップに対してのみ(またはタップカウントが10000を超える場合)、「タップ」を出力します。
downloadButton.rx_tap
.window(timeSpan: 3, count: 10000, scheduler: MainScheduler.instance)
.flatMap({ observable -> Observable<Void> in
return observable.take(1)
})
.subscribeNext { _ in
NSLog("tap")
}.addDisposableTo(bag)
ウィンドウは優れたソリューションですが、サンプルオペレーターの方が直感的であり、動作も適切です。
messagesHandler.messages
.sample(Observable<Int>.timer(0.0, period: 2.0, scheduler: MainScheduler.instance))
.subscribeNext { [weak self] message in
self?.playMessageArrivedSound()
}.addDisposableTo(self.disposeBag)
スロットル操作で思った通りに動きません。
スロットルもわかりにくいと感じる人にとっては:
「スロットルは、ソースオブザーバブルが指定された期間イベントの送信を停止した場合にのみイベントを転送します。これは、通常のイベント配信ではうまく機能しません。」 詳細について 。
この場合、必要なフィルターは
sample(Observable<Int>.timer(0.0, period: 2.0, scheduler: MainScheduler.instance))