Swift愛好会 Advent Calendar 2017の12日目担当の @dekatotoroです。
昨日は、 @marty-suzukiさんの 「Swift4からprotocolのassociatedtypeでできるようになったこと」 でした。
今日は**「RxSwiftのDebounceとThrottle」**についてです。
RxSwiftのoperatorにDebounceとThrottleがありますが、
「あれ、どっちがどういう動作だったっけ?」と思ったことはありませんか。
忘れたときはこの記事を見てみてください
パターンは3つあります。
- Debounce
- Throttle (latest true)
- Throttle (latest false)
以下のストリームをを例にします。
※ 確認したversionは RxSwift 4.0.0
let observable = Observable<Int>.create { observer in
observer.onNext(1)
observer.onNext(2)
observer.onNext(3)
sleep(2)
observer.onNext(4)
observer.onNext(5)
observer.onNext(6)
sleep(2)
observer.onCompleted()
return Disposables.create()
}
Debounce
指定期間新たなイベントが発行されなくなってから、最後に発行されたイベントを発行します。途中のイベントは無視されます。
_ = observable
.debounce(1, scheduler: scheduler) // 3, 6
.subscribe(onNext: {
print("debounce: \($0)")
})
Throttle
RxSwift 3.4.0からlatestパラメーターが追加されています。
defaultはtrueです。
計測が開始された最初のイベントと、指定期間内で最後に発行されたイベント(最初のイベント以外)を発行します。途中のイベントは無視します。
latestがfalseの場合は、計測が開始された最初のイベントを発行し、指定期間内のイベントは全て無視します。
debounceとの違いは、指定期間の計測が開始された最初のイベントを発行すること、latestがtrueの場合は指定期間内で発行されたイベント(最初のイベント以外)が指定期間経つと必ず発行するところです。
Throttle (latest true)
_ = observable
.throttle(1, latest: true, scheduler: scheduler) // 1, 3, 4, 6
.subscribe(onNext: {
print("throttle true: \($0)")
})
Throttle (latest false)
_ = observable
.throttle(1, latest: false, scheduler: scheduler) // 1, 4
.subscribe(onNext: {
print("throttle false: \($0)")
})
Example
実際に使用する例です。
debounceはインクリメンタルサーチなどでAPIを叩き過ぎないようにするのに便利ではないでしょうか。
throttle latest falseはボタン連打防止など色々用途がありそうです。
throttle latest trueはあまり使い所が思い浮かばないなので、使ってる方は使用例ご教授ください
class ViewController: UIViewController {
@IBOutlet private weak var searchBar: UISearchBar!
@IBOutlet private weak var button: UIButton!
private let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
searchBar.rx.text
.debounce(0.3, scheduler: MainScheduler.instance)
.subscribe(onNext: { text in
print("UISearchBar debounce: \(text ?? "") \(Date())")
})
.disposed(by: disposeBag)
button.rx.tap.asObservable()
.throttle(1.0, latest: false, scheduler: MainScheduler.instance)
.subscribe(onNext: { _ in
print("UIButton throttle latest false: \(Date())")
})
.disposed(by: disposeBag)
}
}
以上になります
Swift愛好会 Advent Calendar 2017 明日は @mizukoA になります!