项目中需要
- 连续点击按钮只让第一次生效,用 throttle 操作符即可;
- 搜索时文本不断变化导致调用多次接口,用 debounce 操作符即可;
实现之后发现每次都要写同样的三四行代码,很啰嗦不说,也不利于统一配置,顺手简易封装,记录一下。
throttle 与 debounce区别总结如下:
Throttle(节气门):每个指定时间段内最多调用一次原始函数。
Debounce(防抖): 原始函数被调用 调用者在指定时间段后停止调用修饰的函数.
🌰🌰:
//浅封装:
button.rx.safeDrive { (sender) in
DDLog(sender.currentTitle as Any)
}.disposed(by: dispose)
searchBar.rx.safeDrive { (query) in
DDLog(query)
}.disposed(by: dispose)
//极简封装:
button.rxDrive { (sender) in
DDLog(sender.currentTitle as Any)
}.disposed(by: dispose)
searchBar.rxDrive { (query) in
DDLog(query)
}.disposed(by: dispose)
源码
//
// RXCocoaHelper.swift
// SwiftTemplet
//
// Created by Bin Shang on 2020/12/24.
// Copyright © 2020 BN. All rights reserved.
//
import UIKit
import RxSwift
import RxCocoa
public extension Reactive where Base: UIButton {
var safeTap: ControlEvent<Void> {
return ControlEvent.init(events: tap.throttle(.milliseconds(1500), latest: false, scheduler: MainScheduler.instance))
}
///避免连续点击(1.5 秒响应一次)
func safeDrive(onNext: @escaping ((Base) -> Void)) -> Disposable {
return self.safeTap
.asControlEvent()
.asDriver()
.drive {
onNext(self.base)
} onCompleted: {
} onDisposed: {
}
}
}
public extension Reactive where Base: UITextField {
///避免连续调用(1.5 秒响应一次)
func safeDrive(_ dueTime: RxSwift.RxTimeInterval = .milliseconds(1500), onNext: @escaping ((String) -> Void)) -> Disposable {
return text.orEmpty
.asDriver()
.distinctUntilChanged()
.debounce(dueTime)
.drive(onNext: { (query) in
onNext(query)
}) {
} onDisposed: {
}
}
}
public extension Reactive where Base: UISearchBar{
///避免连续调用(1.5 秒响应一次)
func safeDrive(_ dueTime: RxSwift.RxTimeInterval = .milliseconds(1500), onNext: @escaping ((String) -> Void)) -> Disposable {
return text.orEmpty
.asDriver()
.distinctUntilChanged()
.debounce(dueTime)
.drive(onNext: { (query) in
onNext(query)
}) {
} onDisposed: {
}
}
}
public extension UIButton{
///避免连续调用(1.5 秒响应一次)
func rxDrive(onNext: @escaping ((UIButton) -> Void)) -> Disposable {
return self.rx.safeDrive(onNext: onNext)
}
}
public extension UITextField{
///避免连续调用(1.5 秒响应一次)
func rxDrive(onNext: @escaping ((String) -> Void)) -> Disposable {
return self.rx.safeDrive(onNext: onNext)
}
}
public extension UISearchBar{
///避免连续调用(1.5 秒响应一次)
func rxDrive(onNext: @escaping ((String) -> Void)) -> Disposable {
return self.rx.safeDrive(onNext: onNext)
}
}
网友评论