简体   繁体   中英

How to restart or stop a Timer in Swift without destroying it?

I'm developing an iOS application using a bluetooth device with a button that is communicating with the iPad. Basically I want a help request to be issued when the button is held for 3 seconds or longer.

From all the documentation I found, I couldn't find a way to stop a Timer without invalidating it, with the invalidate() method. From Apple's documentation :

The run loop then removes the timer (and the strong reference it had to the timer), either just before the invalidate() method returns or at some later point. Once invalidated, timer objects cannot be reused.

So the idea in my code is that when the button is pressed, the boolean buttonWasHeld is set to true and a timer is fired. If the button is released, buttonWasHeld is set to false and, when the timer calls the handler it knows the button wasn't held long enough. Then if the button is pressed again within the 3 seconds, the timer is set over again.

Problem is: every button press makes a new timer, which means that repeatedly pressing the button will also issue the help request. Furthermore, all those timers are addressed by the same variable so I can't tell them apart.

Is there a way to uniquely tell what was the last timer created? Or an obscure way to pause/stop it?

Here's the piece of code controlling this feature:

var buttonTimer: Timer?
var buttonWasHeld: Bool = false

func didUpdateModule() {
    // gpioListener takes a handler to be called whenever a button is
    // pressed or released. isPushed is a self-explanatory boolean.
    self.controller.gpioListener() { isPushed in
        if isPushed {
            self.buttonWasHeld = true
            self.buttonTimer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false) { _ in
                if self.buttonWasHeld {
                    // Issue a help request
                    self.delegate?.notifyDevice(message: .HELP)
                    print("Asking for help")
                }
            }
            print("Button was pressed")
        }
        else {
            self.buttonWasHeld = false
            // Also tried "self.buttonTimer = nil" here. Didn't work
            print("Button was released")
        }
    }
}

As usual, the answer was quite simple.

If the Timer is declared as a weak var , and not just var , only the weak instantiation will be invalidated. So the code should be:

weak var buttonTimer: Timer?
var buttonWasHeld: Bool = false

func didUpdateModule () {
    (...)
        else {
            // This will only invalidate the current running timer,
            // not the whole variable :)
            self.buttonTimer.invalidate
            // I removed buttonWasHeld, it's not necessary anymore ;)
            print("Button was released")
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM