0

I translated some code from a storyboard to be created programmatically. So why isn't my gesture recognizer getting called when I programmatically create a gesture recognizer?

There are other SO posts about ensuring UIView.isUserInteractionEnabled is enabled on the view and that's not the problem. I've also tried setting the UIGestureRecognizerDelegate: In gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) I see my gesture triggering and always returning true doesn't help. Yes, I am installing the gesture recognizer with UIView.addGestureRecognizer(_:)!

class ExampleView: UIView {
  let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(myAction(_:)))

  required init?(coder: NSCoder) {
    super.init(coder: coder)
    commonInit()
  }

  override init(frame: CGRect) {
    super.init(frame: frame)
    commonInit()
  }

  @objc func myAction(_ sender: UITapGestureRecognizer) {
    print("never happens")
  }

  private func commonInit() {
    isUserInteractionEnabled = true
    tapGestureRecognizer.delegate = self
    addGestureRecognizer(tapGestureRecognizer)
  }
}

extension ExampleView: UIGestureRecognizerDelegate {
  func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
  }
}
slythfox
  • 545
  • 6
  • 12
  • Can you provide the full snippet, including where you add the gesture recognizer? There's not enough code here to figure out what's going on. – kid_x May 14 '21 at 17:55
  • @kid_x To be clear, I posted this to answer my own question as my answer wasn't appropriate for other questions on gesture recognizers. Although I have elaborated upon the example I am concerned it may muddy the water. https://stackoverflow.com/help/self-answer – slythfox May 14 '21 at 20:06

1 Answers1

0

It looks like you can't create a target action referencing self at initialization time of a class where self isn't available yet. I'm not sure why there's not a warning or error for this.

There are two possible workarounds:

  1. Although it's missing from the UIGestureRecognizer documentation there is a vanilla init method with no parameters. Use that and then call UIGestureRecognizer.addTarget(_:action:) sometime after initialization.

  2. Use a lazy property

private lazy var tapGestureRecognizer: UITapGestureRecognizer = { .init(target: self, action: #selector(myAction)) }()

slythfox
  • 545
  • 6
  • 12