扬庆の博客

rxSwift写一个倒计时定时器?

字数统计: 402阅读时长: 1 min
2021/04/16 Share

rxSwift 倒计时定时器?

swift 写一个定时器比较简单了, 常用的获取验证码的时候会用到; 这次我们使用 rxSwift 写一个定时器含有倒计时功能

手机验证码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
rxSwift - 按钮点击倒计时定时器



import RxSwift
import RxCocoa

public class XTimer: NSObject {
/// 默认计时时间
public var defaultTime: Int = 60
// 绑定计时器到timerSwitch
public let isRunning: BehaviorRelay<Bool> = BehaviorRelay(value: false)
/// 剩余时间
private lazy var residueTime = BehaviorRelay(value: defaultTime)

/// 计时器
private var timer: DispatchSourceTimer? = nil
/// 进入后台通知监听
private var didEnterBackground: Disposable? = nil
/// 进入前台通知监听
private var willEnterForeground: Disposable? = nil


deinit {
dPrint(#function)
invalidate()
}
}

extension XTimer {
/// 开始计时
public func fire() -> Observable<String> {
// 初始化
invalidate()

// 更新计时状态
isRunning.accept(true)

// 计算进入 app 进入后台的时间
var enterBackgroundDate: Date? = nil
didEnterBackground = NotificationCenter.default.rx
.notification(UIApplication.didEnterBackgroundNotification)
.subscribe { _ in
dPrint("进入后台了")
enterBackgroundDate = Date()
}

willEnterForeground = NotificationCenter.default.rx
.notification(UIApplication.willEnterForegroundNotification)
.subscribe { [unowned self] _ in
dPrint("进入前台了")
let time = self.residueTime.value - Int(round(Date().timeIntervalSince(enterBackgroundDate!)))
self.residueTime.accept(time)
}


// 创建计时器
let timer = DispatchSource.makeTimerSource(queue: .global())
timer.schedule(deadline: .now(), repeating: .seconds(1))
timer.setEventHandler { [weak self] in
self?.updateResidueTime()
}
timer.resume()
self.timer = timer

return residueTime
.withLatestFrom(Observable.just(defaultTime), resultSelector: { t, defaultTime -> String in
return t == defaultTime ? "重新获取" : "\(t)s"
})
.share(replay: 1)
}

/// 销毁
public func invalidate() {
// 销毁计时
timer?.cancel()
// 销毁通知监听
didEnterBackground?.dispose()
willEnterForeground?.dispose()
}

private func updateResidueTime() {
let time = residueTime.value - 1
if time <= 0 {
// 销毁 timer
invalidate()
// 结束计时
isRunning.accept(false)
// 恢复默认
residueTime.accept(defaultTime)
} else {
residueTime.accept(time)
}
}
}




封装好的, 可以直接贴出去使用

如需转载说明出处~

CATALOG
  1. 1. rxSwift 倒计时定时器?