When the UITapGestureRecognizer
is not added to the view, both the UIButton
and CustomControl
will receive the .touchUpInside
event. However, when the UITapGestureRecognizer
is added to the view, only the UIButton
can receive the .touchUpInside
event. How can a custom UIControl
be configured to respond to the touch event like UIButton
in this scenario?
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let uiButton = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
uiButton.backgroundColor = .red
uiButton.addTarget(self, action: #selector(onUIButtonClick), for: .touchUpInside)
view.addSubview(uiButton)
let customButton = CustomControl(frame: CGRect(x: 200, y: 100, width: 100, height: 100))
customButton.backgroundColor = .blue
customButton.addTarget(self, action: #selector(onCustomControlClick), for: .touchUpInside)
view.addSubview(customButton)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onTap))
view.addGestureRecognizer(tapGesture)
}
@objc func onTap() {
debugPrint("onTap")
}
@objc func onUIButtonClick() {
debugPrint("onUIButtonClick")
}
@objc func onCustomControlClick() {
debugPrint("onCustomControlClick")
}
}
class CustomControl: UIControl {
}
2
Answers
The tap gesture will not cancel touches for other views in its view’s hierarchy if
cancelsTouchesInView
is set to false. This manner, the tap gesture will not interfere with the touch events of the custom control.The delegate method gestureRecognizerShouldBegin(_:) asks if the gesture should read (and interrupt) touches. In your case:
You can expand the conditional if you don’t want other gestures to interrupt either.