Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITapGestureRecognizer doesn't work for .began state

I've added two gesture recognizers to my UIView:

func tap(sender: UITapGestureRecognizer){
    if sender.state == .began {
        print("snapping photo")
    }

}
func longPress(sender: UILongPressGestureRecognizer) {
    if sender.state == .began {
        print("snapping video")
    }
}

When both are set to state == .began, only longPress fires. When I set tap to .ended, both fire.

Why doesn't tap work when its state is set to .began?

like image 555
Nick Barr Avatar asked Nov 05 '14 18:11

Nick Barr


1 Answers

The Handling UIKit Gestures tells us:

Gesture recognizers come in two types: discrete and continuous. A discrete gesture recognizer calls your action method exactly once after the gesture is recognized. After its initial recognition criteria are met, a continuous gesture recognizer performs calls your action method many times, notifying you whenever the information in the gesture’s event changes.

...

The state property of a gesture recognizer communicates the object’s current state of recognition. For continuous gestures, the gesture recognizer updates the value of this property from .began to .changed to .ended, or to .cancelled. Your action methods use this property to determine an appropriate course of action.

The UITapGestureRecognizer is a discrete gesture, and as such, your event handler is called once when the gesture was recognized. In practice, this means that your tap gesture recognizer handler will not be called for a state of .began. It is, however, called for a state of .ended.

(The Handling UIKit Gestures documentation tells us that the handler of a discrete gesture will be called “exactly once”. This is consistent with my experience. Confusingly, the tap gesture documentation and the Handling Tap Gestures reference suggest that one should test for a state of .ended even though, in practice, that’s the only state for which your tap gesture handler will ever be called. Regardless, while it might be prudent to look for a state of .ended, don’t ever expect to ever see a state of .began in your discrete gesture handlers.)

The UILongPressGestureRecognizer, on the other hand, is a continuous gesture, so checking the state is very useful (determining when the gesture .began, .changed, .ended, etc.). That's why you see it called for the state of .began.

like image 177
Rob Avatar answered Oct 05 '22 19:10

Rob