UITapGestureRecognizer not working on UILabel but working on parent view

Viewed 1469

View hierarchy is like this,

- control (UIView)
 - container (UIView)
     - icon (UILabel)
     - label(UILabel)

If I try to add Tap gesture on control, it works perfectly. If I try to addTap gesture on any of the other items, it doesn't work.

isUserInteractionEnabled is enabled for every element. I also called BringToFront for each element.

I also tried to set UIGestureRecognizerDelegate and detect Touch event, it isn't detecting as well.

Any idea?

Here is the code,

func setGesture() {
//        self.isUserInteractionEnabled = true
//        containerView.isUserInteractionEnabled = true
        label.isUserInteractionEnabled = true
//        exclamationMark.isUserInteractionEnabled = true

        self.bringSubview(toFront: containerView)
        containerView.bringSubview(toFront: exclamationMark)

        label.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTapSavingLabel)))
        //exclamationMark.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTapExclamationMarkButton)))
        //self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(selfTapped)))
    }

    @objc func didTapExclamationMarkButton() {
        delegate?.didTapExclamationMarkButton()
    }

    @objc func didTapSavingLabel() {
        delegate?.didTapSavingLabel()
    }

    @objc func selfTapped() {
        print("Self Tapped")
    }

If i uncomment the Tap gesture on Self, it works well.

2 Answers

The problem is that one or more of the label's superview has a frame size of 0,0. When that view's .clipsToBounds property is false, it allows its subviews (the label, in this case) to be seen on-screen, but it extends outside the bounds of its superview.

Any view in that condition will not respond to touches / gestures.

Once you solve your layout issues and have the frames properly set up, the Tap Gesture added to the label will work as intended.

I created the outlet in Interface Builder and connect to label var.

Updated to new answer. I think you have "exclamation" view over the label.

The rest is the next code.

- controller
-- container
--- label


class ViewController: UIViewController {

    @IBOutlet weak var container: UIView!
    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.label.isUserInteractionEnabled = true
        self.view.bringSubviewToFront(self.container)


        let tap = UITapGestureRecognizer(target: self, action: #selector(tapPerformed(_:)))
        self.label.addGestureRecognizer(tap)

    }

    @objc func tapPerformed(_ tap: UITapGestureRecognizer) {
        debugPrint(#function)
    }
}
Related