0

I have a custom UIGestureRecognizer subclass that detects a particular kind of one-finger dragging. On the same scene, I also have a UIPinchGestureRecognizer, that detects two-finger pinches.

The problem happens when the user makes a pinch gesture but puts down one finger an instant before the other: the custom gesture recognizer sees a single touch and engages (sets its state to .began) and the pinch recognizer doesn't. When the second touch is added, the custom recognizer notices and switches its state to .failed. But it's too late and the pinch gesture recognizer doesn't pick it up.

Here's the code for the custom UIGestureRecognizer subclass:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
    super.touchesBegan(touches, with: event)
    guard touches.count == 1 else {
        state = .failed
        return
    }
    state = .began
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
    super.touchesMoved(touches, with: event)
    guard touches.count == 1 else {
        state = .failed
        return
    }
    // do gesture recognizer stuff here
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
    super.touchesEnded(touches, with: event)
    state = .ended
}

I've tried it with cancelsTouchesInView set to false and with delaysTouchesBegan set to true for the custom gesture recognizer. Neither made a difference in this behavior.

When I use a UIPinchGestureRecognizer with a UIPanGestureRecognizer I don't have this issue, which leads me to think it's not the intended behavior.

What's wrong with my UIGestureRecognizer fail code and how can I fix it so that a UIPinchGestureRecognizer can still recognize pinches where the touches start non-simultaneously?

Robert
  • 6,660
  • 5
  • 39
  • 62

1 Answers1

0

Try using the UIGestureRecognizerDelegate protocol to implement gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:). That can allow you to have two gestures be recognized simultaneously.

class MyVC: UITableViewController, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        let pinchGestureRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(handlePinchFrom))
        pinchGestureRecognizer.delegate = self
        view.addGestureRecognizer(pinchGestureRecognizer)
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}
peacetype
  • 1,928
  • 3
  • 29
  • 49