「Swift」Timer倒计时和正向计时

371 阅读1分钟
引言:有时需要用到Timer计时器的倒计时,如登录时重新发送验证码时间间隔;或者需要用到Timer的正向计时,如需要进行轮询上报信息或获取相应信息

贴代码

import Foundation

public typealias TimerBlock = (Int) -> ()
public typealias TimerCompleteBlock = () -> ()

public class Timer {
    var timer: DispatchSourceTimer?
    
    public init() {
        
    }
}

public extension Timer {
    /// 倒计时
    /// - Parameters:
    /// - maxTime: 倒计时时间秒数
    /// - timerBlock: 倒计时进行中回调
    /// - complete: 倒计时结束时回调
    func startTiming(maxTime: Int, timerBlock: @escaping TimerBlock, complete: @escaping TimerCompleteBlock) {
        timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())
        timer?.schedule(deadline: .now(), repeating: .seconds(1))
        
        // 结束时间
        let endTime = NSDate.init(timeIntervalSinceNow: TimeInterval(maxTime))
        
        timer?.setEventHandler {
            let intinterval = endTime.timeIntervalSinceNow
            
            if intinterval >= 0 {
                DispatchQueue.main.async {
                    timerBlock(Int(intinterval))
                    print("计时为:\(Int(intinterval))")
                }
                
            } else {
                self.timer?.cancel()
                
                DispatchQueue.main.async {
                    complete()
                }
            }
        }
        timer?.resume()
    }
    
    /// 正向计时
    /// - Parameters:
  	/// - startTime: 起始时间 格式为:yyyy-MM-dd HH:mm:ss
  	/// - timerBlock: 倒计时回调
    func startPositiveTiming(startTime: String, timerBlock: @escaping TimerBlock) {
        timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())
        timer?.schedule(deadline: .now(), repeating: .seconds(1))
        
        // 结束时间
        let format = DateFormatter()
        format.dateFormat = "yyyy-MM-dd HH:mm:ss"
        let startDate = format.date(from: startTime)
        
        if startDate == nil {
            return
        }
        
        timer?.setEventHandler {
            let endTime = Date()
            let intinterval = endTime.timeIntervalSince(startDate!)
            
            DispatchQueue.main.async {
                timerBlock(Int(intinterval))
                print("计时为:\(Int(intinterval)),记得调用cancelTiming()方法取消计时")
            }
        }
        timer?.resume()
    }
    
    /// 取消计时
    func cancelTiming() {
        if timer != nil {
            timer!.cancel()
            timer = nil
        }
    }
}

方法使用:

private var timer = Timer()
private var countDownTimer = Timer()
/// 倒计时方法使用
countDownTimer.startTiming(maxTime: 60) { value in
	/// 每次倒计时进行时的回调,通常用于修改UI展示
    print(\(value))
    
} complete: {
	/// 倒计时结束时回调
	/// 取消计时
    self.countDownTimer.cancelTiming()
	///处理一些逻辑判断和UI展示
	//xxxx
}


/// 正向计时方法使用
/// Date().dateString(dateformatter: "yyyy-MM-dd HH:mm:ss")以yyyy-MM-dd HH:mm:ss格式输入当前时间
timer.startPositiveTiming(startTime: Date().dateString(dateformatter: "yyyy-MM-dd HH:mm:ss")) { value in
 	    /// 每次计时时进行的回调
 	    /// ps:注意逻辑判断成功后需手动进行计时器取消,否则会浪费内存占用
}

整理不易,请大家多多点赞收藏,谢谢大家!