Swift-带条件的GCD计时器

时间:2018-12-26 10:08:06

标签: swift timer swift4 grand-central-dispatch dispatch-queue

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

RappleActivityIndicatorView.setProgress(CGFloat(a), textValue: "\(String(a * 100)) %")
print("\(a) %")

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

我在想一个GCD计时器:

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

但是我不知道如何链接15秒内未更新的值的条件。 有什么想法吗?

非常感谢

2 个答案:

答案 0 :(得分:2)

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

您需要一个属性,即计时器参考

var timeoutTimer : DispatchSourceTimer?

然后创建一个启动计时器的方法。如果(单次)计时器未运行,则创建该计时器,如果正在运行,则重新启动。在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)
    }
}

要控制计时器,您需要为当前百分比值设置另一个属性

var currentValue : CGFloat = 0.0

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

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

上传成功后,删除计时器

self.timeoutTimer!.cancel()
self.timeoutTimer = nil

答案 1 :(得分:1)

尝试一下:

var timer: Timer?

// every time you set new percent start new Timer. if in 15 sec it will not reach new percent -> cancellation begins
func startNewTimer() {
    timer?.invalidate()
    timer = Timer.scheduledTimer(withTimeInterval: 15, repeats: false, block: { (_) in
        // do cancellation
    })
}