RxSwift 中的 throttle 与 debounce 封装记录

项目中需要

  1. 连续点击按钮只让第一次生效,用 throttle 操作符即可;

  2. 搜索时文本不断变化导致调用多次接口,用 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)
    }
}
(0)

相关推荐