GestureRecognizer not responding to tap
IosSwiftUigesturerecognizerIos 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.
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)
}
}