Swift - 具有 GCD 和条件的计时器

Vic*_*tor 0 timer grand-central-dispatch swift swift4 dispatch-queue

我使用 Firebase 上传带有进度指示器的文件:

RappleActivityIndicatorView.setProgress(CGFloat(a), textValue: "\(String(a * 100)) %")
print("\(a) %")
Run Code Online (Sandbox Code Playgroud)

我想实现一个条件:如果 % 的值(例如:23%)停留 15 秒或更长时间,则会取消上传。

我正在考虑一个 GCD 计时器:

 DispatchQueue.main.asyncAfter(deadline: .now() + 15) {
        print("We can launch the cancellation of the upload")
    }
Run Code Online (Sandbox Code Playgroud)

但我不知道如何链接 a 值在 15 秒内未更新的条件。任何想法 ?

多谢,

vad*_*ian 5

一个合适的解决方案是超时计时器。GCD 定时器的好处是它可以在运行时重新启动。

您需要一个属性,即计时器引用

var timeoutTimer : DispatchSourceTimer?
Run Code Online (Sandbox Code Playgroud)

然后创建一个方法来启动计时器。如果(一次性)计时器未运行,则创建该计时器;如果正在运行,则重新启动。在 15 秒后执行的事件处理程序中,打印该行并释放计时器。

func startTimeoutTimer()
{
    let delay : DispatchTime = .now() + .seconds(15)
    if timeoutTimer == nil {
        timeoutTimer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())
        timeoutTimer!.schedule(deadline: delay, repeating: 0)
        timeoutTimer!.setEventHandler {
            self.timeoutTimer!.cancel()
            self.timeoutTimer = nil
            print("We can launch the cancellation of the upload")
        }
        timeoutTimer!.resume()
    } else {
        timeoutTimer?.schedule(deadline: delay, repeating: 0)
    }
}
Run Code Online (Sandbox Code Playgroud)

要控制计时器,您需要另一个属性来表示当前百分比值

var currentValue : CGFloat = 0.0
Run Code Online (Sandbox Code Playgroud)

设置过程后,将值与当前值进行比较,如果值不同,则(重新)启动计时器。如果值相等,则计时器在 15 秒延迟后触发。如果进度继续,例如 8 秒后,计时器将再次从零开始。

RappleActivityIndicatorView.setProgress(CGFloat(a), textValue: "\(String(a * 100)) %")
if a != currentValue {
    startTimeoutTimer()
    currentValue = a
} 
Run Code Online (Sandbox Code Playgroud)

当上传成功完成后删除计时器

self.timeoutTimer!.cancel()
self.timeoutTimer = nil
Run Code Online (Sandbox Code Playgroud)