224

I have a UIView and and I have added tap gesture to it:

let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
tap.delegate = self
myView.addGesture(tap)

I am trying to call it programmatically in the testfile.

sendActionForEvent

I am using this function, but it is not working:

myView.sendActionForEvent(UIEvents.touchUpDown)

It shows unrecognised selector sent to instance.

How can I solve this problem?

H. Pauwelyn
  • 13,575
  • 26
  • 81
  • 144
George
  • 3,600
  • 2
  • 26
  • 36
  • 3
    In swift 2.2 you can use new selector syntax: let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:))) – Wujo Apr 05 '16 at 09:22
  • @wujo - thanks for that; strangely it doesn't actually work for me, in a UIView Maybe only in a view controller? – Fattie May 29 '16 at 20:47
  • 2
    Also remember to have `imageView.userInteractionEnabled = true` if you're using an image view. Got caught on that for too long. – Josh Aug 30 '16 at 17:11
  • @Josh, yes an important point. – NeverHopeless Aug 01 '18 at 14:08
  • @George have you found the solution yet? I'm having the same concern with you. But my purpose is for unit test, where I want to trigger the tap on the view. Thanks – azun Mar 03 '20 at 08:30
  • 1
    @KhangAzun the best option is to call the tap function directly – George Mar 04 '20 at 05:40

24 Answers24

328

You need to initialize UITapGestureRecognizer with a target and action, like so:

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

Then, you should implement the handler, which will be called each time when a tap event occurs:

@objc func handleTap(_ sender: UITapGestureRecognizer? = nil) {
    // handling code
}

So now calling your tap gesture recognizer event handler is as easy as calling a method:

handleTap()
Mohit Kumar
  • 2,898
  • 3
  • 21
  • 34
Salavat Khanov
  • 4,100
  • 2
  • 15
  • 27
  • 1
    instead of calling selector function directly, i want to call it by programmatically invoking UITapGestureRecognizer event – George Feb 23 '15 at 14:19
  • 2
    @muhasturk Don't change the meaning of an upvoted answer. Your edit was invalidating the answer for older Swift versions. If you want to post an update for Swift 2.2, post your own answer. Thank you. – Eric Aya Apr 15 '16 at 11:35
  • 23
    `tap.delegate = self` is not needed, since you already set a target and action – Daniel Jul 27 '17 at 08:45
  • 4
    Throws an error in Swift3, your handle tap function should be: func handleTap(_ sender: UITapGestureRecognizer) – Travis M. May 09 '18 at 20:17
  • Calling function should be................func handleTap(_ sender: UITapGestureRecognizer? = nil) ...............you missed "_"........so your calling function was not working.. – Prasad Patil Jun 11 '18 at 12:44
120

For anyone who is looking for Swift 3 solution

let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))

view.addGestureRecognizer(tap)

view.isUserInteractionEnabled = true

self.view.addSubview(view)

// function which is triggered when handleTap is called
@objc func handleTap(_ sender: UITapGestureRecognizer) {
     print("Hello World")
  }
Naresh
  • 16,698
  • 6
  • 112
  • 113
John Lim
  • 3,019
  • 4
  • 31
  • 41
67

For Swift 4:

let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))

view.addGestureRecognizer(tap)

view.isUserInteractionEnabled = true

self.view.addSubview(view)

// function which is triggered when handleTap is called
@objc func handleTap(_ sender: UITapGestureRecognizer) {
    print("Hello World")
}

In Swift 4, you need to explicitly indicate that the triggered function is callable from Objective-C, so you need to add @objc too your handleTap function.

See @Ali Beadle 's answer here: Swift 4 add gesture: override vs @objc

RNHTTR
  • 2,235
  • 2
  • 15
  • 30
52

Just a note - Don't forget to enabled interaction on the view:

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

view.addGestureRecognizer(tap)

// view.userInteractionEnabled = true

self.view.addSubview(view)
muhasturk
  • 2,534
  • 20
  • 16
eclewlow
  • 931
  • 9
  • 9
28

Implementing tap gesture

let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "touchHappen") 
view.userInteractionEnabled = true
view.addGestureRecognizer(tap)

Calls this function when the tap is recognized.

func touchHappen() {
    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    self.view.endEditing(true)
}

Update for For Swift 3 +

let tap = UITapGestureRecognizer(target: self, action: #selector(self.touchHappen(_:)))
yourView.addGestureRecognizer(tap)
yourView.userInteractionEnabled = true

func touchHappen(_ sender: UITapGestureRecognizer) {
    print("Hello Dear you are here")
}
Museer Ahamad Ansari
  • 5,414
  • 3
  • 39
  • 45
23

STEP : 1

@IBOutlet var viewTap: UIView!

STEP : 2

var tapGesture = UITapGestureRecognizer()

STEP : 3

override func viewDidLoad() {
    super.viewDidLoad()
    // TAP Gesture
    tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.myviewTapped(_:)))
    tapGesture.numberOfTapsRequired = 1
    tapGesture.numberOfTouchesRequired = 1
    viewTap.addGestureRecognizer(tapGesture)
    viewTap.isUserInteractionEnabled = true
}

STEP : 4

func myviewTapped(_ sender: UITapGestureRecognizer) {

    if self.viewTap.backgroundColor == UIColor.yellow {
        self.viewTap.backgroundColor = UIColor.green
    }else{
        self.viewTap.backgroundColor = UIColor.yellow
    }
}

OUTPUT

enter image description here

Kirit Modi
  • 23,155
  • 15
  • 89
  • 112
19

Swift 5.1 Example for three view

Step:1 -> Add storyboard view and add outlet viewController UIView

@IBOutlet var firstView: UIView!
@IBOutlet var secondView: UIView!
@IBOutlet var thirdView: UIView!

Step:2 -> Add storyBoard view Tag

firstView secondView thirdView

Step:3 -> Add gesture

override func viewDidLoad() {
        super.viewDidLoad()

        firstView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tap(_:))))
        firstView.isUserInteractionEnabled = true
        secondView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tap(_:))))
        secondView.isUserInteractionEnabled = true
        thirdView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tap(_:))))
        thirdView.isUserInteractionEnabled = true
    }

Step:4 -> select view

@objc func tap(_ gestureRecognizer: UITapGestureRecognizer) {
        let tag = gestureRecognizer.view?.tag
        switch tag! {
        case 1 :
            print("select first view")
        case 2 :
            print("select second view")
        case 3 :
            print("select third view")
        default:
            print("default")
        }
    }
ikbal
  • 1,110
  • 12
  • 21
  • 1
    You can delete the lines "isUserInteractionEnabled = true" and put the value directly on Attributes Inspector, just below "Tag" you have "User Interaction Enabled" with a check-box. – Xav Mac Mar 19 '21 at 20:15
13

Swift 4

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

@objc func touchTapped(_ sender: UITapGestureRecognizer) {
}
Giang
  • 3,553
  • 30
  • 28
8

This is how it works in Swift 3:

@IBOutlet var myView: UIView!
override func viewDidLoad() {
    super.viewDidLoad()

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

    myView.addGestureRecognizer(tap)
}

func handleTap() {
    print("tapped")
}
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Neen
  • 361
  • 4
  • 5
8

try the following extension

extension UIView {
    
    func  addTapGesture(action : @escaping ()->Void ){
        let tap = MyTapGestureRecognizer(target: self , action: #selector(self.handleTap(_:)))
        tap.action = action
        tap.numberOfTapsRequired = 1
        
        self.addGestureRecognizer(tap)
        self.isUserInteractionEnabled = true
        
    }

    @objc func handleTap(_ sender: MyTapGestureRecognizer) {
        sender.action!()
    }
}

class MyTapGestureRecognizer: UITapGestureRecognizer {
    var action : (()->Void)? = nil
}

and then use it :

submitBtn.addTapGesture {
     //your code
}

you can even use it for cell

cell.addTapGesture {
     //your code
}
Md. Ibrahim Hassan
  • 5,359
  • 1
  • 25
  • 45
mahdi delavar
  • 188
  • 2
  • 4
  • 3
    While a code-only answer is indeed an answer, a bit of explanation (why the OP's code did not work, what is the general idea behind your code, important points, warnings, ...) could make it a *better* answer. – lfurini Jan 16 '19 at 17:36
7

Complete answer for Swift 4

Step 1: create an outlet for the view

@IBOutlet weak var rightViewOutlet: UIView!

Step 2: define a tap gesture

var tapGesture = UITapGestureRecognizer()

Step 3: create ObjC function (called when view tapped)

@objc func rightViewTapped(_ recognizer: UIGestureRecognizer) {
    print("Right button is tapped")
}

Step 4: add the following within viewDidLoad()

let rightTap = UITapGestureRecognizer(target: self, action: #selector(ViewController.rightViewTapped(_:)))
    rightViewOutlet.addGestureRecognizer(rightTap)
George
  • 183
  • 2
  • 10
7

Here is the simplest way to add Gestures on View in Swift 5

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        addGestures()
    }

    // MARK: Add Gestures to target view
    func addGestures()
    {
        // 1. Single Tap or Touch
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapGetstureDetected))
        tapGesture.numberOfTapsRequired = 1
        view.addGestureRecognizer(tapGesture)

        //2. Double Tap
        let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(self.doubleTapGestureDetected))
        doubleTapGesture.numberOfTapsRequired = 2
        view.addGestureRecognizer(doubleTapGesture)

        //3. Swipe
        let swipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(self.swipeGetstureDetected))
        view.addGestureRecognizer(swipeGesture)

        //4. Pinch
        let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(self.pinchGetstureDetected))
        view.addGestureRecognizer(pinchGesture)

        //5. Long Press
        let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGetstureDetected))
        view.addGestureRecognizer(longPressGesture)

        //6. Pan
        let panGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.panGestureDetected))
        view.addGestureRecognizer(panGesture)

    }

    // MARK: Handle Gesture detection
    @objc func swipeGetstureDetected() {
        print("Swipe Gesture detected!!")
    }

    @objc func tapGetstureDetected() {
        print("Touch/Tap Gesture detected!!")
    }

    @objc func pinchGetstureDetected() {
        print("Pinch Gesture detected!!")
    }

    @objc func longPressGetstureDetected() {
        print("Long Press Gesture detected!!")
    }

    @objc func doubleTapGestureDetected() {
        print("Double Tap Gesture detected!!")
    }

    @objc func panGestureDetected()
    {
        print("Pan Gesture detected!!")
    }


    //MARK: Shake Gesture
    override func becomeFirstResponder() -> Bool {
        return true
    }
    override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?){
        if motion == .motionShake
        {
            print("Shake Gesture Detected")
        }
    }
}
swiftBoy
  • 35,607
  • 26
  • 136
  • 135
6

I worked out on Xcode 6.4 on swift. See below.

var view1: UIView!

func assignTapToView1() {          
  let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap"))
  //  tap.delegate = self
  view1.addGestureRecognizer(tap)
  self.view .addSubview(view1)

...
}

func handleTap() {
 print("tap working")
 view1.removeFromSuperview()
 // view1.alpha = 0.1
}
Hugo Alonso
  • 6,684
  • 2
  • 34
  • 65
Alvin George
  • 14,148
  • 92
  • 64
5

You need to initialize UITapGestureRecognizer with a target and action, like so:

let tap = UITapGestureRecognizer(target: self, action: "handleTap:")
tap.delegate = self
myView.addGestureRecognizer(tap)

Then, you should implement the handler, which will be called each time when a tap event occurs:

func handleTap(sender: UITapGestureRecognizer) {
  // handling code
}
Forge
  • 6,538
  • 6
  • 44
  • 64
Amit Raj Modi
  • 86
  • 1
  • 2
5

If you want Objective C code is given below,

UITapGestureRecognizer *gesRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; // Declare the Gesture.
gesRecognizer.delegate = self;
[yourView addGestureRecognizer:gesRecognizer]; // Add Gesture to your view.

// Declare the Gesture Recognizer handler method.

- (void)handleTap:(UITapGestureRecognizer *)gestureRecognizer{
   NSLog(@"Tapped");
}

or you want swift code is given below,

import UIKit
class ViewController: UIViewController {

    @IBOutlet weak var myView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Add tap gesture recognizer to view
        let tapGesture = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
        myView.addGestureRecognizer(tapGesture)
    }

    // this method is called when a tap is recognized
    func handleTap(sender: UITapGestureRecognizer) {

        print("tap")
    }
}
Iyyappan Ravi
  • 3,205
  • 2
  • 16
  • 30
3
    let tap = UITapGestureRecognizer(target: self, action: Selector("handleFrontTap:"))
    frontView.addGestureRecognizer(tap)

// Make sure this is not private
func handleFrontTap(gestureRecognizer: UITapGestureRecognizer) {
    print("tap working")
}
Axel Guilmin
  • 11,454
  • 9
  • 54
  • 64
Pramod
  • 1,123
  • 2
  • 12
  • 33
3

Swift 4

First, create an object of UITapGestureRecognizer

var tapGesture = UITapGestureRecognizer()

The second step is to initialise UITapGestureReconizer. Enable the user interaction, then add it.

override func viewDidLoad() {
        super.viewDidLoad()
    tapGesture = UITapGestureRecognizer(target: self, action: #selector(YourViewController.myviewTapped(_:)))
            infosView.isUserInteractionEnabled = true
            infosView.addGestureRecognizer(tapGesture)
view.addSubview(infosView)
}

Third, create a method

@objc func myviewTapped(_ recognizer: UIGestureRecognizer) {
                print("button is tapped")
            }
Md. Ibrahim Hassan
  • 5,359
  • 1
  • 25
  • 45
Akbar Khan
  • 2,215
  • 19
  • 27
2

I worked out on Xcode 7.3.1 on Swift 2.2. See below.

func addTapGesture() {
    let tap = UITapGestureRecognizer(target: self, action: #selector(MyViewController.handleTap))
    tap.numberOfTapsRequired = 1
    self.myView.addGestureRecognizer(tap)
}

func handleTap() {
    // Your code here...
}
1

I wanted to specify two points which kept causing me problems.

  • I was creating the Gesture Recognizer on init and storing it in a let property. Apparently, adding this gesture recog to the view does not work. May be self object passed to the gesture recognizer during init, is not properly configured.
  • The gesture recognizer should not be added to views with zero frames. I create all my views with zero frame and then resize them using autolayout. The gesture recognizers have to be added AFTER the views have been resized by the autolayout engine. So I add the gesture recognizer in viewDidAppear and they work.
nnrales
  • 1,481
  • 1
  • 17
  • 26
1

xCode 9.3, Swift 4.0

class BaseVC: UIViewController, UIGestureRecognizerDelegate { 

      @IBOutlet weak var iView: UIView!

      override func viewDidLoad() {
          super.viewDidLoad()
          let clickUITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.onSelect(_:)))
          clickUITapGestureRecognizer.delegate = self
          iView?.addGestureRecognizer(tap)
      }

      func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
          return true
      }


     @IBAction func onSelect(_ sender: Any) {

     }
}
Rahul
  • 337
  • 3
  • 13
  • The function onSelect don't need to be IBAction – Illya Krit Jul 04 '18 at 12:01
  • iView?.addGestureRecognizer(tap) The name of your gestureRecognizer is clickUITapGestureRecognizer So the right way is: iView?.addGestureRecognizer(clickUITapGestureRecognizer) – Illya Krit Jul 04 '18 at 12:03
1

Inside ViewDidLoad

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
    self.imgMainAdView.isUserInteractionEnabled = true
    self.imgMainAdView.addGestureRecognizer(tapGestureRecognizer)

//MARK: - Image Tap Method -
@objc func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
    print("Tapped")
    if let url = URL(string: self.strMAinAdvLink)
    {
        UIApplication.shared.open(url, options: [:])
    }
}

Calling Purpose

@IBAction func btnCall1Action(_ sender: Any)
{
    let text = self.strPhoneNumber1!
    let test = String(text.filter { !" -()".contains($0) })
    UIApplication.shared.openURL(NSURL(string: "tel://\(test)")! as URL)
}

Mail Purpose

MFMailComposeViewControllerDelegate

 @IBAction func btnMailAction(_ sender: Any)
{
    let strEmail = SAFESTRING(str:  (self.dictEventDetails?.value(forKeyPath: "Email.value_text.email") as! String))

    if !MFMailComposeViewController.canSendMail()
    {
        AppDelegate.sharedInstance().showAlertAction(strTitle: "OK", strMessage: "Mail services are not available") { (success) in
        }
        return
    }
    let composeVC = MFMailComposeViewController()
    composeVC.mailComposeDelegate = self
    composeVC.setToRecipients([strEmail])
    composeVC.setSubject("")
    composeVC.setMessageBody("", isHTML: false)
    self.present(composeVC, animated: true, completion: nil)
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?)
{
    controller.dismiss(animated: true, completion: nil)
}
Tej Patel
  • 119
  • 2
  • 5
0

Try the following swift code (tested in Xcode 6.3.1):

    import UIKit

    class KEUITapGesture150427 : UIViewController {
      var _myTap: UITapGestureRecognizer?
      var _myView: UIView?

      override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.whiteColor();

        _myTap = UITapGestureRecognizer(target: self
, action: Selector("_myHandleTap:"))
        _myTap!.numberOfTapsRequired = 1

        _myView = UIView(frame: CGRectMake(100, 200, 100, 100))
        _myView!.backgroundColor=UIColor.blueColor()
        _myView!.layer.cornerRadius = 20
        _myView!.layer.borderWidth = 1
        _myView!.addGestureRecognizer(_myTap!)
        view.addSubview(_myView!)
      }

      func _myHandleTap(sender: UITapGestureRecognizer) {
        if sender.state == .Ended {
          println("_myHandleTap(sender.state == .Ended)")
          sender.view!.backgroundColor
          = UIColor(red: CGFloat(drand48()), green: CGFloat(drand48()), blue: CGFloat(drand48()), alpha: 1.0);
        }
      }
    }

Note that your target could be any subclass of UIResponder, see (tested in Xcode 6.3.1):

    import UIKit

    class MyTapTarget  : UIResponder {
      func _myHandleTap2(sender: UITapGestureRecognizer) {
        if sender.state == .Ended {
          println("_myHandleTap2(sender.state == .Ended)")
          sender.view!.backgroundColor
            = UIColor(red: CGFloat(drand48()), green: CGFloat(drand48()), blue: CGFloat(drand48()), alpha: 1.0);
        }
      }
    }

    class KEUITapGesture150427b : UIViewController {
      var _myTap: UITapGestureRecognizer?
      var _myView: UIView?
      var _myTapTarget: MyTapTarget?

      override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.whiteColor();

        _myTapTarget = MyTapTarget()
        _myTap = UITapGestureRecognizer(target: _myTapTarget!
, action: Selector("_myHandleTap2:"))
        _myTap!.numberOfTapsRequired = 1

        _myView = UIView(frame: CGRectMake(100, 200, 100, 100))
        _myView!.backgroundColor=UIColor.blueColor()
        _myView!.layer.cornerRadius = 20
        _myView!.layer.borderWidth = 1
        _myView!.addGestureRecognizer(_myTap!)
        view.addSubview(_myView!)
      }
    }
Dmitry Konovalov
  • 508
  • 7
  • 16
0

Instead of invoking myView's UITapGestureRecognizer, you can directly call the handleTap function,

budiDino
  • 13,044
  • 8
  • 95
  • 91
0

For anyone looking to activate a views tap gesture recognizer without having direct access to the gesture recognizer... when returning to a page I had to fill bubbles that were previously filled by tapping. I kept track of those bubbles tags (bubs) ...

func fillBubs(bubs: [Int]) {
    for bub in bubs {
        let bubble = view.viewWithTag(bub)
        if bubble == nil {continue}
        for g in bubble!.gestureRecognizers! {
            let tap = g as! UITapGestureRecognizer
            handleBub(tap)
        }
    }
}

@objc func handleBub(_ sender: UITapGestureRecognizer? = nil) {
    let bubble = sender?.view!
    bubble?.layer.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
}