GestureRecognizer not responding to tap

IosSwiftUigesturerecognizer

Ios Problem Overview


After initialisation of by subclass of UIImageView I have the following line of code:

self.userInteractionEnabled = true
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "handleTap:"))

I created the necessary associated function :

func handleTap(gestureRecognizer: UITapGestureRecognizer) {
    print("In handler")
}

On tapping on the view in question, "In handler was never printed to the console". I then removed the handler function to see if the compiler would complain about the missing function. It didn't.

I'm positively stumped. I'd truly appreciate any light people can shed on this.

Update: My class is actually a UIImageView as opposed to UIView

Ios Solutions


Solution 1 - Ios

I was using UITapGestureRecognizer that I placed on a UILabel using Storyboard.

To get this to work I also had to place a checkmark in the block labeled: "User Interaction Enabled" in the UILabel Attributes Inspector in the Storyboard.

enter image description here

Solution 2 - Ios

I discovered the answer after carefully combing through my code.

One of the parent views was created without supplying a frame:

While it's a noobish enough error to warrant deletion of this questions, odds are someone else will also have the same issue in the future...

Solution 3 - Ios

Try this

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    self.view.userInteractionEnabled = true
    var tapGesture = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    self.view.addGestureRecognizer(tapGesture)
}

func handleTap(sender : UIView) {
    println("Tap Gesture recognized")
}

Solution 4 - Ios

In addition to the other answers, this can be caused by adding the gesture recognizer to multiple views. Gesture recognizers are for single views only.

Reference: https://stackoverflow.com/a/5567684/6543020

Solution 5 - Ios

I ran into this problem with programmatic views.

My UIView with the gesture recognizer had .isUserInteractionEnabled = true, but it did not respond to taps until I set .isUserInteractionEnabled = true for its parent views as well.

Solution 6 - Ios

Most likely you add UIGestureRecognizer in wrong place. Here is working sample with UIView from storyboard. If you create your UIView dynamically then you should put this initialization in the correct constructor.

class TestView: UIView
{
    override func awakeFromNib()
    {
        self.userInteractionEnabled = true
        self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "handleTap:"))
    }
    
    func handleTap(gestureRecognizer: UITapGestureRecognizer)
    {
        println("Here")
    }
}

Solution 7 - Ios

I found the solution to this problem after lot of trial and error. So there are two solution two this

1. Either add the GestureRecognizer in viewDidLoad() and turn userInteractionEnabled = true

2. If using computed property use lazy var instead of let to the property.

lazy var profileImageView: UIImageView = {
    let iv = UIImageView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
    iv.image = #imageLiteral(resourceName: "gameofthrones_splash")
    iv.contentMode = .scaleAspectFill
    iv.translatesAutoresizingMaskIntoConstraints = false
    iv.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleSelectProfileImageView)))
    iv.isUserInteractionEnabled = true
    return iv
}()

Solution 8 - Ios

This Code works for me with XCode 7.0.1

import UIKit

class ImageView: UIImageView {
    
    init(frame: CGRect, sender: Bool, myImage: UIImage) {
        super.init(frame: frame)
        self.image = myImage
        initBorderStyle(sender)
        
        // enable user interaction on image.
        self.userInteractionEnabled = true
        let gesture = UITapGestureRecognizer(target: self, action: "previewImage:")
        addGestureRecognizer(gesture)
        
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    func previewImage(myGesture: UITapGestureRecognizer? = nil) {
        print("i'm clicked")
    }
    
    private func initBorderStyle(sender: Bool) {
        self.layer.masksToBounds = true
        self.layer.cornerRadius = 8
        self.layer.borderWidth = 0.5
        self.layer.borderColor = getBorderColor(sender)
        self.backgroundColor = getColor(sender)
    }
    
    
    func getBorderColor(sender: Bool) -> CGColor {
        var result: CGColor
        if sender {
            result = UIColor(red: 0.374, green: 0.78125, blue: 0.0234375, alpha: 0.5).CGColor
        } else {
            result = UIColor(red: 0.3125, green: 0.6015625, blue: 0.828125, alpha: 0.5).CGColor
        }
        return result
    }
}

Solution 9 - Ios

Xcode 11.4 Swift 5.2

UserInteraction is enabled by default on Custom UIView

import UIKit

class YourView: UIView {
        
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    
    func commonInit() {
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapped))
        self.addGestureRecognizer(tapGesture)
    }
    
    @objc func tapped() {
        // do something
    }
}

If you want to be notified elsewhere that the custom UIView has been tapped, then it is convenient to use a Notification.

It is best to create this as an extension to prevent it being Stringly typed.

extension Notification.Name {
    static let DidTapMyView = Notification.Name("DidTapMyView")
}

In your custom UIView when the tapped function is called

@objc func tapped() {
    NotificationCenter.default.post(name: .DidTapMyView, object: self)
}

In your UIViewController where you want to listen for the Notification:

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(myViewWasTapped), name: .DidTapMyView, object: nil)
}

@objc func myViewWasTapped() {
    // Notified here - do something
}

Solution 10 - Ios

For anyone that is still having problems even with all the previous answers, make sure you are using UITapGestureRecognizer instead of UIGestureRecognizer, I kept missing this detail while trying to find what was wrong.

Solution 11 - Ios

In addition the above (userInteractionEnabled, clipsToBounds, etc.), if you are working with a view in a child view controller be sure that you have added it as a child with myParentViewController.addChild(myChildViewController) — we've run into a couple of situations now where visible views were not firing recognizing gestures because their view controllers hadn't been added, and presumably the VCs themselves were not being retained.

Solution 12 - Ios

Here's a list of my findings in 2021, XCode 13:

  • Make sure both your view and all of its superviews have set width & height constraints(this one is crucial)
  • Set isUserInteractionEnabled = true for your view
  • There's no need to set explicit frame or isUserInteractionEnabled for other super views

Solution 13 - Ios

It turned out that my gesture didn't work because it was in a normal class, and not a subclass of UIView or anything.

I solved the issue by creating a subclass of UIView that I had an instance of in this normal class and placed the gesture logic in that.

Solution 14 - Ios

I solved my issue by setting the height to the UIView.

optionView.heightAnchor.constraint(equalToConstant: 18).isActive = true

Solution 15 - Ios

I had the same issue in my programmatically created ViewController. The bug was fixed when I added a backgroundColor to the view.

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .systemBackground
        
        let tap = UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing))

        view.addGestureRecognizer(tap)

    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDidiaView Question on Stackoverflow
Solution 1 - IosScooterView Answer on Stackoverflow
Solution 2 - IosDidiaView Answer on Stackoverflow
Solution 3 - IosSuresh Kumar DurairajView Answer on Stackoverflow
Solution 4 - IosbradkratkyView Answer on Stackoverflow
Solution 5 - IosmattdedekView Answer on Stackoverflow
Solution 6 - IosVitalyView Answer on Stackoverflow
Solution 7 - IosMayank WadhwaView Answer on Stackoverflow
Solution 8 - IosTarekView Answer on Stackoverflow
Solution 9 - IosrbaldwinView Answer on Stackoverflow
Solution 10 - IosJalxPView Answer on Stackoverflow
Solution 11 - IosJeffView Answer on Stackoverflow
Solution 12 - IosAdam BardonView Answer on Stackoverflow
Solution 13 - IosGeorgeView Answer on Stackoverflow
Solution 14 - Iosuser6573749View Answer on Stackoverflow
Solution 15 - IosLennyView Answer on Stackoverflow