RxSwift implements countdown
Use RxSwift to realize the countdown, need to rely on takeWhile to judge the true condition, otherwise the sequence will keep on timing, the main code is as follows a big pile
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("Get it again".for: .normal)
self.viewModel.getSMSEableObserable.accept(true)
}).disposed(by: self.disposeBag)
}, onError: { (error) in
}).disposed(by: disposeBag)
Copy the code
explain
Action
The viewModel. GetSMScodeAction. Elements. ObserveOn (MainScheduler. Instance returns a Obserable, on the main thread to subscribe to it, get is, click to get verification code, The successful closure {} for executing the network request is where the countdown is implemented. The viewModel getSMScodeAction is an Action the Action is such a class
public final class Action<Input, Element>
Copy the code
An input, and an Element, in which elements is an Observable of the Action
public let elements: Observable<Element>
Copy the code
The map, takeWhile
Observable
. Interval (1, scheduler: mainScheduler.instance) is an Observable with an interval of 1 that uses map to convert to the remaining time. The type stays the same and the meaning changes
If the countdown time is greater than 0, the mapResult will be executed. If the countdown time is greater than 0, the mapResult will be executed
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("Get it again".for: .normal)
self.viewModel.getSMSEableObserable.accept(true)
}).disposed(by: self.disposeBag)
Copy the code
Pay attention to
When the conditions of the takeWhile are not met, it terminates and goes onCompleted{} without skipping the current value
For example,
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 3, 2, 1)
.takeWhile { $0 < 4 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
Copy the code
If I get to the first 1,2,3, I stop and I don’t output anything after 4