Reputation: 81
I use Firebase to upload a file with a progress indicator:
RappleActivityIndicatorView.setProgress(CGFloat(a), textValue: "\(String(a * 100)) %")
print("\(a) %")
I want to implement a condition : if the value of the % (for eg : 23%) is stuck for 15 sec or more, it launch a cancel of the upload.
I was thinking of a GCD Timer :
DispatchQueue.main.asyncAfter(deadline: .now() + 15) {
print("We can launch the cancellation of the upload")
}
But I don't know how to link the condition of the a value not updated during 15 seconds. Any idea ?
Thanks a lot,
Upvotes: 0
Views: 1345
Reputation: 285250
A suitable solution is a timeout timer. The benefit of a GCD timer is it can be restarted while running.
You need one property, the timer reference
var timeoutTimer : DispatchSourceTimer?
Then create a method to start the timer. The (one-shot) timer is created if it's not running and restarted if it's running. In the event handler which is executed after the 15 seconds the line is printed and the timer is deallocated.
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)
}
}
To control the timer you need another property for the current percent value
var currentValue : CGFloat = 0.0
When the process is set compare the value with the current value and (re)start the timer if the values are different. If the values are equal the timer fires after the delay of 15 seconds. If the progress continues for example after 8 seconds the timer starts again from zero.
RappleActivityIndicatorView.setProgress(CGFloat(a), textValue: "\(String(a * 100)) %")
if a != currentValue {
startTimeoutTimer()
currentValue = a
}
And when the upload is finished successfully delete the timer
self.timeoutTimer!.cancel()
self.timeoutTimer = nil
Upvotes: 5
Reputation: 212
Try this:
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
})
}
Upvotes: 1