Swift 延时执行、倒计时、定时器

延时执行

代码块的延时运行我们很常见也很常用,不少封装都不错也易于使用。在GCD的基础上我们可以将代码延时运行封装得更好用一些,再加上可以取消延时的功能,我们通过捕获一个cancel标识变量来实现delay call的取消,下面是完整的封装方法,可以尝试调用看看~

    typealias Task = (_ cancel: Bool) -> Void
    /// 代码延迟运行
    ///
    /// - Parameters:
    ///   - delayTime: 延时时间。比如:.seconds(5)、.milliseconds(500)
    ///   - qosClass: 要使用的全局QOS类(默认为 nil,表示主线程)
    ///   - task: 延迟运行的代码
    /// - Returns: Task?
    @discardableResult
    static func bk_delay(by delayTime: TimeInterval, qosClass: DispatchQoS.QoSClass? = nil, _ task: @escaping () -> Void) -> Task? {
        
        func dispatch_later(block: @escaping () -> Void) {
            let dispatchQueue = qosClass != nil ? DispatchQueue.global(qos: qosClass!) : .main
            dispatchQueue.asyncAfter(deadline: .now() + delayTime, execute: block)
        }
        
        var closure: (() -> Void)? = task
        var result: Task?
        
        let delayedClosure: Task = { cancel in
            if let internalClosure = closure {
                if !cancel {
                    DispatchQueue.main.async(execute: internalClosure)
                }
            }
            closure = nil
            result = nil
        }
        
        result = delayedClosure
        
        dispatch_later {
            if let delayedClosure = result {
                delayedClosure(false)
            }
        }
        
        return result
        
    }

    /// 取消代码延时运行
    func delayCancel(_ task: Task?) {
        task?(true)
    }

使用的时候就很简单啦~如下调用:

delay(by: 3) { print("3秒后执行") }

想要取消的话,我们可以先保留一个对Task的引用,然后调用delayCancel:

let task = delay(by: 2) { print("2秒后执行") }
// 不执行了,还是取消掉吧
delayCancel(task)

倒计时

这里分享的也是GCD的倒计时封装,比起Timer项目中要根据自身情况合理使用不同计时方法。

    /// GCD定时器倒计时
    ///
    /// - Parameters:
    ///   - timeInterval: 间隔时间
    ///   - repeatCount: 重复次数
    ///   - handler: 循环事件,闭包参数: 1.timer 2.剩余执行次数
    func dispatchTimer(timeInterval: Double, repeatCount: Int, handler: @escaping (DispatchSourceTimer?, Int) -> Void) {
        
        if repeatCount <= 0 {
            return
        }
        let timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)
        var count = repeatCount
        timer.schedule(deadline: .now(), repeating: timeInterval)
        timer.setEventHandler {
            count -= 1
            DispatchQueue.main.async {
                handler(timer, count)
            }
            if count == 0 {
                timer.cancel()
            }
        }
        timer.resume()
        
    }

定时器

直接上代码啦~

    /// GCD实现定时器
    ///
    /// - Parameters:
    ///   - timeInterval: 间隔时间
    ///   - handler: 事件
    ///   - needRepeat: 是否重复
    func dispatchTimer(timeInterval: Double, handler: @escaping (DispatchSourceTimer?) -> Void, needRepeat: Bool) {
        
        let timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)
        timer.schedule(deadline: .now(), repeating: timeInterval)
        timer.setEventHandler {
            DispatchQueue.main.async {
                if needRepeat {
                    handler(timer)
                } else {
                    timer.cancel()
                    handler(nil)
                }
            }
        }
        timer.resume()
        
    }

总之,GCD的使用方法多种多样,多多练习尝试使用~

联系方式:[email protected]
Kim 写于2020.9.2,希望文章能对你有所帮助。

你可能感兴趣的:(Swift 延时执行、倒计时、定时器)