I have a theory about why this is happening.
To illustrate, imagine we're making our own back button. It should have the following behavior to mimic Apple's:
- On touch down, call
backspacePressed
- After .5 seconds, if touch is still down, call
backspacePressed
again
- After every .1 seconds, if touch is still down, call
backspacePressed
again
Here's how I would implement it:
Add this to the end of your viewDidLoad
let button = UIButton(type: .system)
button.setTitle("Tap Me", for: .normal)
button.addTarget(self, action: #selector(ViewController.handleButtonTouched(button:)), for: .touchDown)
button.addTarget(self, action: #selector(ViewController.handleButtonReleased(button:)), for: .touchUpInside)
button.frame = CGRect(x: 50, y: newField.frame.maxY, width: 200, height: 150)
view.addSubview(button)
Add this after viewDidLoad
var buttonTimer: Timer?
func handleButtonTouched(button: UIButton) {
buttonTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false, block: { [weak self] timer in
print("button's been held down for a while!")
self?.backspacePressed()
self?.buttonTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { (timer) in
print("button's still held down")
self?.backspacePressed()
})
})
print("button was pressed") // add a breakpoint here
self.backspacePressed()
}
func handleButtonReleased(button: UIButton) {
buttonTimer?.invalidate()
}
(Optional) Comment out your log so your console matches mine for this experiment
func backspacePressed( ){
//print("in backspacePressed")
}
Without a breakpoint, if you tap and hold this button, you'll get logs printed following the behavior I outlined above:
button was pressed
button's been held down for a while!
button's still held down
button's still held down
button's still held down
button's still held down
If you just tap the button (don't hold it), you'll just get
button was pressed
However, if you set the breakpoint, tap the button, and wait for a second after the breakpoint hits before pressing continue, you get two logs:
button was pressed
button's been held down for a while!
You'd think, since you didn't hold the button for long enough, you wouldn't get the second log. What's happening is the timer is ticking down even though you're stopped on a breakpoint, and when execution returns to the program, the result of the timer is evaluated before the button release is evaluated.
I'm not exactly sure why things happen in this order - why can't the button release be handled before the timer event? But you can see that in normal execution without a breakpoint, it's not even a question of what happens first - a short button tap will cause handleButtonReleased to be called before the timer can go off.
I suspect that in your case, Apple's keyboard is doing something similar, and you're setting a breakpoint that's holding your touch in stasis while a timer somewhere decides that yes, this is indeed a long press! Even though it really isn't. I don't have a workaround, but hopefully this shines some light on what's happening.