手势识别器、UIControl 和 UIButton 的事件响应优先级

Event response priorities for gesture recognizers, UIControl, and UIButton

提问人:Yasic 提问时间:10/20/2023 更新时间:10/20/2023 访问量:36

问:

我有一个添加了手势识别器的父视图。父视图包含一个 UIButton 和一个 UIControl,分别添加了相应的操作。

代码如下

class MyViewController: UIViewController {
    
     private lazy var parentView = UIView()
     private lazy var button = UIButton(frame: .zero)
     private lazy var control = UIControl(frame: .zero)
    
     override func viewDidLoad() {
         super.viewDidLoad()
        
         view.backgroundColor = .white
         view.addSubview(parentView)
         parentView.addSubview(button)
         parentView.addSubview(control)
        
         parentView.backgroundColor = .red
         button.backgroundColor = .yellow
         control.backgroundColor = .blue
        
         let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleParentViewTapped))
         parentView.addGestureRecognizer(tapGesture)
         button.addTarget(self, action: #selector(handleButtonClicked), for: .touchUpInside)
         control.addTarget(self, action: #selector(handleControlClicked), for: .touchUpInside)
        
         parentView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
         }
         button.snp.makeConstraints { make in
             make.leading.top.equalToSuperview()
             make.size.equalToSuperview().multipliedBy(0.5)
         }
         control.snp.makeConstraints { make in
             make.trailing.bottom.equalToSuperview()
             make.size.equalToSuperview().multipliedBy(0.5)
         }
     }
    
     @objc func handleParentViewTapped() {
         print("view tapped")
     }
    
     @objc func handleButtonClicked() {
         print("button clicked")
     }
    
     @objc func handleControlClicked() {
         print("UIControl clicked")
     }

}

我依次点击了 UIButton 和 UIControl,控制台打印顺序如下

button clicked
view tapped

如您所见,单击 UIButton 可以触发 UIButton 对应的操作,但单击 UIControl 将触发手势识别器的回调。

接下来,我将父视图的手势识别器设置为 false。这一次,手势识别器、UIButton 和 UIControl 的回调都将被调用。cancelsTouchesInView

view tapped
button clicked
view tapped
UIControl clicked

我的问题是

  1. 既然 UIButton 也是从 UIControl 继承而来的,为什么 UIButton 的事件响应优先级高于父视图的手势识别器,而 UIControl 却低于父视图的手势识别器?
  2. 如果我有一个自定义的 UIControl,并且想要达到与 UIButton 相同的优先级效果,我应该如何实现?
  3. 我知道如果手势识别器的cancelsTouchesInView设置为false,则click事件将继续传递给UIControl,因此UIControl可以响应该事件。但是,为什么 UIButton 和手势识别器都可以在 cancelsTouchesInView 设置为 false 后响应事件?
iOS UIBuint UIGoogerRecognizer UIContations

评论


答: 暂无答案