swift UITapGestureRecognizer not working on view

user7804097 picture user7804097 · Nov 15, 2017 · Viewed 12.2k times · Source

I had to create a new thread bcoz it's driving me crazy and all the other answers online are exactly the same. I have done this countless of times but I cannot see what I am missing for the life of me. I am using a "test" view controller just to get the tap gesture working but it isn't working at all... I am fairly certain that I am setting this up correctly, as this is how I've always implemented it in the past: (yes, I have checked the box for isUserInteractionEnabled). I am even implementing this on a different viewcontroller this exact way and it is working...

class TestViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
    view.addGestureRecognizer(tap)
  }

  let tap = UITapGestureRecognizer(target: self, action: #selector(wasTapped))

    
  @objc func wasTapped() {
    print("tapped")
  }
}

I have also tried adding the parameters to wasTapped:

@objc func wasTapped(gestureRecognizer: UITapGestureRecognizer) {
  print("tapped")
}

Answer

matt picture matt · Nov 15, 2017

You are saying:

override func viewDidLoad() {
    super.viewDidLoad()

    view.addGestureRecognizer(tap)
}

let tap = UITapGestureRecognizer(target: self, action: #selector(wasTapped))

The problem is the last line:

let tap = UITapGestureRecognizer(target: self, action: #selector(wasTapped))

You cannot just say let tap like that in the middle of nowhere. You are implicitly making an instance property. But you cannot initialize an instance property with a target of self, because self does not exist at the time an instance property is initialized. (I regard the fact that that code even compiles as a bug, and have reported it as such.)

Move that line to the start of viewDidLoad, like this:

override func viewDidLoad() {
    super.viewDidLoad()

    let tap = UITapGestureRecognizer(target: self, action: #selector(wasTapped))
    view.addGestureRecognizer(tap)
}