当 UILongPressGestureRecognizer minimumPressDuration 为零时,UIView touchesBegan 不会触发

UIView touchesBegan won't fire when UILongPressGestureRecognizer minimumPressDuration zero

如果手势 minimumPressDuration 设置为“.zero”,

MyView 和 ViewController 的 touchesBegan 将不会触发,但只要我将其设置为“.leastNormalMagnitude”,它就会触发。这是代码:

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)
    }
}

我想我可以将它与“.leastNormalMagnitude”一起使用,但我还是想知道为什么会这样?

尽管在必须使用 UITapGestureRecognizer 的场景中误用了 UILongPressGestureRecognizer,但我将专注于回答“为什么”部分。

当您设置 gesture.minimumPressDuration = .zero 时,长按手势会立即被识别。

默认情况下,手势识别器倾向于延迟视图中的触摸,并在识别到手势后取消触摸。

为了覆盖此行为,设置

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