RxSwift 实现倒计时

3,087 阅读1分钟

RxSwift 实现倒计时

利用RxSwift 实现倒计时,需要 依靠 takeWhile 来判断为真的条件,否则序列就会一直计时下去 主要代码如下 这么一大坨

viewModel.getSMScodeAction.elements.observeOn(MainScheduler.instance).subscribe(onNext: { [weak self](model) in
                guard let self = self else { return }
            self.viewModel.getSMSEableObserable.accept(false)
            let mapResult:Observable<Int> =  Observable<Int>.interval(1, scheduler: MainScheduler.instance).map { (second) -> Int in
                return TOTAL_SECOND - second
            }
            mapResult.takeWhile {
                $0 > 0
            }.subscribe(onNext: { [weak self](remind) in
                guard let self = self else { return }
                self.smsBtn.setTitle("\(remind)s", for: .normal)
                }, onCompleted: {
                    self.smsBtn.setTitle("再次获取", for: .normal)
                    self.viewModel.getSMSEableObserable.accept(true)
            }).disposed(by: self.disposeBag)
            
            
            }, onError: { (error) in
            
            }).disposed(by: disposeBag)
        

解释一下

Action

viewModel.getSMScodeAction.elements.observeOn(MainScheduler.instance 返回一个在主线程 上的 Obserable, 订阅它,得到的是,点击 获取验证码,执行网络请求的成功的的 闭包{} ,要在这里去实现 倒计时。 其中 viewModel.getSMScodeAction 是一个 Action Action 是这样的一个类

public final class Action<Input, Element>

一个输入,和一个 Element,里面的 elementsAction 的一个属性,是一个 Observable

public let elements: Observable<Element>

map 、takeWhile

Observable<Int>.interval(1, scheduler: MainScheduler.instance) 是一个 间隔为 1 的 Observable 使用 map 函数,转换成 剩余的时间,类型不变,意义变了

这里的 takeWhile 表示 mapResult 继续执行的条件,倒计时的时间 大于 0 就执行, 否则就停下来,重新获取

  mapResult.takeWhile {
                $0 > 0
            }.subscribe(onNext: { [weak self](remind) in
                guard let self = self else { return }
                self.smsBtn.setTitle("\(remind)s", for: .normal)
                }, onCompleted: {
                    self.smsBtn.setTitle("再次获取", for: .normal)
                    self.viewModel.getSMSEableObserable.accept(true)
            }).disposed(by: self.disposeBag)

注意

takeWhile 的条件不符合的时候,直接终止,走 onCompleted{}, 并不会跳过 当前值

例如

let disposeBag = DisposeBag()

Observable.of(1, 2, 3, 4, 3, 2, 1)
    .takeWhile { $0 < 4 }
    .subscribe(onNext: { print($0) })
    .disposed(by: disposeBag)

到前面的 1,2,3,就终止了 4 后面的不会再输出