UIView ClickListener : Swift


Adding a click event to a UIView is something which is required most of the times. For views like UIButton, we can simply connect an IBAction with the event type and detect the click events but sometimes we need it for Lable or even other views.

If you try to add an IBAction to your view, you won't get Action as an option while connecting it with ViewController.
The only possible way to add a click event on UIView is using UITapGestureRecognizer. You can either add an UITapGestureRecognizer using interface builder or you can do it programmatically.
  
//swift code in view controller

let gesture = UITapGestureRecognizer(target: self, action: #selector(self.clickAction(sender:)))
self.myView.addGestureRecognizer(gesture)

func clickAction(sender : UITapGestureRecognizer) {
// Do what you want
}
This way is a bit inefficient as we need to add one function for each view which will be clickable.

There is a better way where we can add this functionality to each view without making our class messy.
We can add this to the UIView extension itself which will be a very clean approach and will make our life super easy.

First, extend UITapGestureRecognizer and add a property to it which holds a function which takes 0 params and is of Void return type.
  
class ClickListener: UITapGestureRecognizer {
var onClick : (() -> Void)? = nil
}
Now create an extension to UIView class and add a method which takes an escaping type of variable which is the reference to a function which need to be run if the view clicked.

Create our ClickListener class object and add a selector to it. Add the passed argument to this ClickListener and add the gesture object to the view.
  
extension UIView {

func setOnClickListener(action :@escaping () -> Void){
let tapRecogniser = ClickListener(target: self, action: #selector(onViewClicked(sender:)))
tapRecogniser.onClick = action
self.addGestureRecognizer(tapRecogniser)
}

@objc func onViewClicked(sender: ClickListener) {
if let onClick = sender.onClick {
onClick()
}
}

}
This took care of all the boilerplate code and added a simple public function to each view for click.

To call this function, simply call setOnClickListener to any view in your view controller.
  
view.setOnClickListener {
print("view clicked")
}
No extra function required in ViewController and it will be very clean.

Complete code