iosswiftuiscrollviewuikituigesturerecognizer

Prevent touches from being passed to views underneath


I have a UIScrollView with a lot of touch handling. I override methods like touchesBegan, touchesMoved, etc. And inside that scroll view, I also have some other views with UIPanGestureRecognizer. The thing is that the subviews gesture doesn't stop the UIScrollView's touch methods completely. It still triggers touchesBegan and touchesMoved on the scroll view a few times before touchesCancelled is called. And all of these triggers are before the recognizer selector is called. Because of this, trying to set isUserInteractionEnabled on the scroll view cannot solve my problem either.

Do we have a way to prevent the touches from going further down in the view hierarchy completely, so that the touch methods of scroll view don't get called at all?

I already tried func point(inside point: CGPoint, with event: UIEvent?) -> Bool { true } and setting cancelsTouchesInView of the gesture recognizer to true.


Solution

  • I believe what you're looking for is delaysTouchesBegan property on the UIGestureRecognizer: https://developer.apple.com/documentation/uikit/uigesturerecognizer/1624234-delaystouchesbegan

    This property defaults to false, but you'll want to set it to true.

    This portion of the linked documentation explains what setting it to true does:

    When the value of the property is true, the window suspends delivery of touch objects in the UITouch.Phase.began phase to the view. If the gesture recognizer subsequently recognizes its gesture, these touch objects are discarded. If the gesture recognizer, however, doesn’t recognize its gesture, the window delivers these objects to the view in a touchesBegan(:with:) message (and possibly a follow-up touchesMoved(:with:) message to inform it of the touches’ current locations). Set this property to true to prevent views from processing any touches in the UITouch.Phase.began phase that may be recognized as part of this gesture.