2

The view controller code below demonstrates my question. It prints some debugging statements in response to touch events and a pinch gesture.

If the gesture recognizer is disabled, and I drag a finger on the screen, everything works as I expected: the controller gets a touchesBegan, a bunch of touchesMoved, and a touchesEnded. But if I enable the gesture recognizer and set its delaysTouchesBegan property to true, and drag a single finger, the controller receives only touchesBegan and touchesEnded calls - no touchesMoved.

The docs for delaysTouchesBegan suggest that touch events will pile up and be delivered after the gesture recognizer fails. Is this the expected behavior - to lose all the touchesMoved events?

class ViewController: UIViewController {

    var gr: UIPinchGestureRecognizer!

    override func viewDidLoad() {
        super.viewDidLoad()
        gr = UIPinchGestureRecognizer(target: self, action: #selector(pinched(_:)))
        gr.delaysTouchesBegan = true
        view.addGestureRecognizer(gr)
    }

    @IBAction func buttonTapped(_ sender: Any) {
        gr.isEnabled = !gr.isEnabled
        print("pinch recognizer enabled: \(gr.isEnabled)")
    }

    @objc func pinched(_ gr: Any?) {
        print("pinched")
    }

    var i = 0

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        i = 0
        print("touchesBegan")
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("touchesMoved \(i)")
        i += 1
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("touchesEnded")
    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("touchesCancelled")
    }
}
Rob N
  • 15,024
  • 17
  • 92
  • 165

1 Answers1

1

A pinch gesture recognizer reports changes each time the distance between the fingers change. The distance between the fingers is reported as a scale factor. So you will want to look at the scale factor, not touchesMoved. Was that helpful?

@objc func pinched(_ gr: UIPinchGestureRecognizer) {

    if gr.state == .began  {
        print("began")
    }

    if gr.state == .changed {
        print("scale: \(gr.scale)")
    }

    if gr.state == .ended {
        print("ended")
    }
}

Handling Pinch Gestures

Handling Pinch Gestures ( Swift 4 - 2018 )

Caleb Wells
  • 11
  • 1
  • 3
  • 1
    I'm talking about the case where I drag a single finger, so the pinch gesture recognizer does not fire. I expected to get touchesMoved for that single finger (but delayed). I will add the word *single* to my question to make this more clear. – Rob N Apr 13 '18 at 23:25
  • Perhaps you could use a pan gesture recognizer then you can track the movement of the user’s finger, and the pinch gesture recognizer will not fire, and use the pinch gesture recognizer without the pan gesture recognizer firing. – Caleb Wells Apr 14 '18 at 01:02
  • 1
    I'm writing a drawing/painting program that needs all the touchesMoved events from finger or stylus. – Rob N Apr 15 '18 at 15:26