MyView's and ViewController's touchesBegan won't fire if gestures minimumPressDuration is set to ".zero" but whenever I set it to ".leastNormalMagnitude" it does. Here is the code:
class ViewController: UIViewController {
let mySuperView: UIView = {
let v = UIView()
v.backgroundColor = .blue
v.frame = CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 500, height: 500))
return v
}()
let mySubview: MyView = {
let v = MyView()
v.backgroundColor = .orange
v.frame = CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 250, height: 250))
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(mySuperView)
mySuperView.addSubview(mySubview)
let gesture = UILongPressGestureRecognizer(target: self, action: #selector(tapped(_:)))
gesture.minimumPressDuration = .zero // when it's set to ".leastNormalMagnitude",
// MyView's and VC's touchesBegan fires.
mySuperView.addGestureRecognizer(gesture)
}
@objc func tapped(_ gesture: UITapGestureRecognizer) {
print("long pressed.")
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("touchesBegan in vc") // -> Won't get called.
super.touchesBegan(touches, with: event)
}
}
class MyView: UIView {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("touchesBegan in MyViewClass") // -> Won't get called.
super.touchesBegan(touches, with: event)
}
}
I guess I can use it with ".leastNormalMagnitude", still I want to know why is this happening?
Despite the misuse of UILongPressGestureRecognizer
for a scenario where UITapGestureRecognizer
has to be used instead, I will focus on answering the "why" part.
When you set gesture.minimumPressDuration = .zero
, the long-press gesture gets instantly recognized.
By default, gesture recognizers tend to delay touches in view, and cancel them if they recognize the gesture.
In order to override this behavior, set
gesture.cancelsTouchesInView = false // to recieve touchesBegan callback even if gesture is recognized
gesture.delaysTouchesBegan = false // to not delay touchesBegan callback
gesture.delaysTouchesEnded = false // to not delay touchesEnded callback