背景:
注册页面或去验证码倒计时功能,如果进入后台后倒计时停止,产品希望即使进入后台后倒计时仍然不会停止。
定时器代码
public class Timer: NSObject {
deinit {
//如果外面不持有会立刻释放,但仍然会倒计时
print("释放了")
}
public var sourceTimer: DispatchSourceTimer?
private var backgroundTaskIdentifier: UIBackgroundTaskIdentifier?
private var duration: TimeInterval
private var interval: TimeInterval
private var intervalBlock: (() -> Void)?
private var endBackgroundBlock: (() -> Void)?
private var completeBlock: (() -> Void)?
init(duration: TimeInterval, interval: TimeInterval, intervalBlock: (() -> Void)?, endBackgroundBlock: (() -> Void)?, completeBlock: (() -> Void)?) {
self.duration = duration
self.interval = interval
self.intervalBlock = intervalBlock
self.endBackgroundBlock = endBackgroundBlock
self.completeBlock = completeBlock
}
public func start() {
var time = self.duration
let sourceTimer = DispatchSource.makeTimerSource()
sourceTimer.schedule(deadline: .now(), repeating: self.interval, leeway: .seconds(1))
sourceTimer.setEventHandler {
if time <= 0 {
sourceTimer.cancel()
DispatchQueue.main.async {
self.completeBlock?()
}
self.endBackGroundTask()
} else {
time -= self.interval
DispatchQueue.main.async {
self.intervalBlock?()
}
}
}
sourceTimer.resume()
self.backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: {
//当程序被挂起时执行这个函数
self.endBackgroundBlock?()
self.endBackGroundTask()
})
self.sourceTimer = sourceTimer
}
public func cancel() {
self.sourceTimer?.cancel()
self.endBackGroundTask()
}
private func endBackGroundTask() {
if let id = backgroundTaskIdentifier {
UIApplication.shared.endBackgroundTask(id)
self.backgroundTaskIdentifier = UIBackgroundTaskInvalid
}
}
}
使用:
@IBAction func btnClick(_ sender: UIButton) {
sender.setTitle("\(10)", for: .normal)
sender.isEnabled = false
var time = 10
Timer(duration: Double(time), interval: 1, intervalBlock: {
sender.setTitle("\(time)", for: .normal)
time -= 1
}, endBackgroundBlock: nil) {
sender.setTitle("获取验证码", for: .normal)
sender.isEnabled = true
}.start()
}
关键字: iOS 倒计时 后台 计时器 Timer