I have a parent view with a gesture recognizer added. The parent view contains a UIButton and a UIControl, with corresponding actions added respectively.
The code is as follows
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")
}
}
I clicked UIButton and UIControl successively, and the console printing sequence is as follows
button clicked
view tapped
As you can see, clicking a UIButton can trigger the action corresponding to the UIButton, but clicking a UIControl will trigger the callback of the gesture recognizer.
Next, I set the cancelsTouchesInView of the parent view's gesture recognizer to false. This time, the callbacks of the gesture recognizer, UIButton, and UIControl will all be called.
view tapped
button clicked
view tapped
UIControl clicked
my question is
- Since UIButton also inherits from UIControl, why is the event response priority of UIButton higher than the gesture recognizer of the parent view, but UIControl is lower than the gesture recognizer of the parent view?
- If I have a custom UIControl and want to achieve the same priority effect as a UIButton, how should I achieve it?
- I know that if the cancelsTouchesInView of the gesture recognizer is set to false, the click event will continue to be passed to the UIControl, so the UIControl can respond to the event. But why can both UIButton and gesture recognizers respond to events after cancelsTouchesInView is set to false?