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,里面的 elements 是 Action 的一个属性,是一个 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 后面的不会再输出