Cancel a Timed Event in Swift

How Do I Cancel and Restart a Timed Event in Swift?

Use a timer:

weak var clearTimer: Timer?

And:

override func viewDidLoad() {
super.viewDidLoad()
startClearTimer()
}

func startClearTimer() {
clearTimer = Timer.scheduledTimer(
timeInterval: 3.0,
target: self,
selector: #selector(clearLabel(_:)),
userInfo: nil,
repeats: false)
}

func clearLabel(_ timer: Timer) {
label.text = ""
}

func volumeSliderValueChange(sender: UISlider) {
clearTimer?.invalidate() //Kill the timer
//do whatever you need to do with the slider value
startClearTimer() //Start a new timer
}

Cancel a timed event in Swift?

Try this (Swift 2.x, see David's answer below for Swift 3):

typealias dispatch_cancelable_closure = (cancel : Bool) -> ()

func delay(time:NSTimeInterval, closure:()->()) -> dispatch_cancelable_closure? {

func dispatch_later(clsr:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(time * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), clsr)
}

var closure:dispatch_block_t? = closure
var cancelableClosure:dispatch_cancelable_closure?

let delayedClosure:dispatch_cancelable_closure = { cancel in
if let clsr = closure {
if (cancel == false) {
dispatch_async(dispatch_get_main_queue(), clsr);
}
}
closure = nil
cancelableClosure = nil
}

cancelableClosure = delayedClosure

dispatch_later {
if let delayedClosure = cancelableClosure {
delayedClosure(cancel: false)
}
}

return cancelableClosure;
}

func cancel_delay(closure:dispatch_cancelable_closure?) {
if closure != nil {
closure!(cancel: true)
}
}

// usage
let retVal = delay(2.0) {
println("Later")
}
delay(1.0) {
cancel_delay(retVal)
}

From Waam's comment here: dispatch_after - GCD in swift?

Cancel scheduled event for background

... when ... pressing stop button ... this is dispatchQueue just keep processing

Yep, this is precisely why you shouldn’t use this multiple asyncAfter pattern. (Plus, you may eventually run into timer coalescing problems.) The Timer is the right way to do this.

So i have this function that should upload some data of a recording every 15 minutes to backend. This should happen even if the user put the app in background.

This is the problem. Neither Timer nor asyncAfter can solve this problem.

I infer that you’ve concluded that you can accomplish this with asyncAfter, but you can’t. Perhaps you were testing this process while running the app attached to the debugger, which artificially keeps the app running in the background. But try it on a device, not attached to the debugger, and you’ll find that the app does not continue to run when the user leaves the app. This asyncAfter technique will not accomplish what you want.

The exception here is if your app has asked for one of the background capabilities (e.g. VOIP, music, navigation, etc.). But if the app is destined for the App Store, Apple is quite diligent in rejecting apps that request background services for unapproved purposes. This sort of constant background operation kills batteries in the matter of hours, so Apple is looking after the best interests of its user base.

So, bottom line, if your app has a background execution capability, a Timer is the way to do this periodic process. And if the app doesn’t have a background execution capability, neither Timer nor any GCD calls will do the job.

Using Swift 3 Stopping a scheduledTimer, Timer continue firing even if timer is nil

Try to make the following changes to your code:

First, you have to change the way you declare timerTest

var timerTest : Timer?

then in startTimer before instantiating check if timerTest is nil

func startTimer () {
guard timerTest == nil else { return }

timerTest = Timer.scheduledTimer(
timeInterval: TimeInterval(0.3),
target : self,
selector : #selector(ViewController.timerActionTest),
userInfo : nil,
repeats : true)
}

Finally in your stopTimerTest you invalidate timerTest if it isn't nil

func stopTimerTest() {
timerTest?.invalidate()
timerTest = nil
}

SwiftUI: How to cancel timer in SwiftUI view?

Inside your conditional statement, use the following code:

self.timer.upstream.connect().cancel()


Related Topics



Leave a reply



Submit