The goal is to perform an action every .5 seconds for as long as a touch is maintained on a button, and to cease that action when the touch has ended. Following advice from other posts here in SO, I have employed a strategy of leveraging a boolean which is set to true on touchDown, and set to false on touchUp. However, it seems that the touchUp func is either not setting the boolean, or the touchDown is ignoring it, because when I lift my finder off the button the action continues.
Here is my touches code:
// MARK: - Touches
func touchDown(atPoint pos : CGPoint) {
print("Touched Down in \(purpose) down arrow")
arrowIsPressed = true
self.texture = SKTexture(imageNamed: "bottomArrowPressed.png")
adjustBlue() // Because you want one immediate action, in case there is no continuous touch
while arrowIsPressed == true {
perform(#selector(callback), with: nil, afterDelay: 1.0)
}
}
func touchUp(atPoint pos : CGPoint) {
arrowIsPressed = false
self.texture = SKTexture(imageNamed: "bottomArrow.png")
adjustCounter = 0
}
// MARK: - Touch Helpers
@objc func callback() {
self.adjustBlue()
}
func adjustBlue() {
adjustCounter += 1
print("Adjust Action \(adjustCounter)")
// eventually useful code will go here
}
Please note that it is a smallish button and I am not concerned at all bout tracking multiple touches.
Where is my logic failing? I feel that this is a fairly straight forward problem and solution but I am doing something wrong and I cannot fathom what.
UPDATE: by placing a print statement inside the while loop I see that the while loop is being called extremely rapidly over and over, even though I have a perform statement inside it with a .5 second delay. Not sure why...
My intuition screams that your while loop blocks the main thread.
The while does not delay between iterations, instead the calling of the callback gets delayed. There are no delays between loops so the main thread gets blocked and the touchup function has no occasion to run.
You could change this to
func touchDown(atPoint pos : CGPoint) {
print("Touched Down in \(purpose) down arrow")
arrowIsPressed = true
self.texture = SKTexture(imageNamed: "bottomArrowPressed.png")
adjustBlue() // Because you want one immediate action, in case there is no continuous touch
callback()
}
func touchUp(atPoint pos : CGPoint) {
arrowIsPressed = false
self.texture = SKTexture(imageNamed: "bottomArrow.png")
adjustCounter = 0
}
// MARK: - Touch Helpers
@objc func callback() {
adjustBlue()
// loop in a non blocking way after 0.5 seconds
DispatchQueue.main.asynAfter(deadline: .now() + 0.5) {
if self.arrowIsPressed {
self.callback()
}
}
}
func adjustBlue() {
adjustCounter += 1
print("Adjust Action \(adjustCounter)")
// eventually useful code will go here
}