[ios] tap gesture recognizer - which object was tapped?

I'm new to gesture recognizers so maybe this question sounds silly: I'm assigning tap gesture recognizers to a bunch of UIViews. In the method is it possible to find out which of them was tapped somehow or do I need to find it out using the point that was tapped on screen?

for (NSUInteger i=0; i<42; i++) {
        float xMultiplier=(i)%6;
        float yMultiplier= (i)/6;
        float xPos=xMultiplier*imageWidth;
        float yPos=1+UA_TOP_WHITE+UA_TOP_BAR_HEIGHT+yMultiplier*imageHeight;
        UIView *greyRect=[[UIView alloc]initWithFrame:CGRectMake(xPos, yPos, imageWidth, imageHeight)];
        [greyRect setBackgroundColor:UA_NAV_CTRL_COLOR];

        greyRect.layer.borderColor=[UA_NAV_BAR_COLOR CGColor];
        greyRect.layer.borderWidth=1.0f;
        greyRect.userInteractionEnabled=YES;
        [greyGridArray addObject:greyRect];
        [self.view addSubview:greyRect];
        NSLog(@"greyGrid: %i: %@", i, greyRect);

        //make them touchable
        UITapGestureRecognizer *letterTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(highlightLetter)];
        letterTapRecognizer.numberOfTapsRequired = 1;
        [greyRect addGestureRecognizer:letterTapRecognizer];
    }

The answer is


Its been a year asking this question but still for someone.

While declaring the UITapGestureRecognizer on a particular view assign the tag as

UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gestureHandlerMethod:)];
[yourGestureEnableView addGestureRecognizer:tapRecognizer];
yourGestureEnableView.tag=2;

and in your handler do like this

-(void)gestureHandlerMethod:(UITapGestureRecognizer*)sender {
    if(sender.view.tag == 2) {
        // do something here
    }
}

in swift it quite simple

Write this code in ViewDidLoad() function

let tap = UITapGestureRecognizer(target: self, action: #selector(tapHandler(gesture:)))
    tap.numberOfTapsRequired = 2
    tapView.addGestureRecognizer(tap)

The Handler Part this could be in viewDidLoad or outside the viewDidLoad, batter is put in extension

@objc func tapHandler(gesture: UITapGestureRecognizer) {
    currentGestureStates.text = "Double Tap"
} 

here i'm just testing the code by printing the output if you want to make an action you can do whatever you want or more practise and read


Use this code in Swift

func tappGeastureAction(sender: AnyObject) {
    if let tap = sender as? UITapGestureRecognizer {
        let point = tap.locationInView(locatedView)
        if filterView.pointInside(point, withEvent: nil) == true {
            // write your stuff here                
        }
    }
}

If you are adding different UIGestureRecognizer on different UIViews and want to distinguish in the action method then you can check the property view in the sender parameter which will give you the sender view.


You should amend creation of the gesture recogniser to accept parameter (add colon ':')

UITapGestureRecognizer *letterTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(highlightLetter:)];

And in your method highlightLetter: you can access the view attached to recogniser:

-(IBAction) highlightLetter:(UITapGestureRecognizer*)recognizer
{
    UIView *view = [recognizer view];
}

func tabGesture_Call
{
     let tapRec = UITapGestureRecognizer(target: self, action: "handleTap:")
     tapRec.delegate = self
     self.view.addGestureRecognizer(tapRec)
     //where we want to gesture like: view, label etc
}

func handleTap(sender: UITapGestureRecognizer) 
{
     NSLog("Touch..");
     //handling code
}

Typical 2019 example

Say you have a FaceView which is some sort of image. You're going to have many of them on screen (or, in a collection view, table, stack view or other list).

In the class FaceView you will need a variable "index"

class FaceView: UIView {
   var index: Int

so that each FaceView can be self-aware of "which" face it is on screen.

So you must add var index: Int to the class in question.

So you are adding many FaceView to your screen ...

let f = FaceView()
f.index = 73
.. you add f to your stack view, screen, or whatever.

You now add a click to f

f.addGestureRecognizer(UITapGestureRecognizer(target: self,
                           action: #selector(tapOneOfTheFaces)))

Here's the secret:

@objc func tapOneOfTheFaces(_ sender: UITapGestureRecognizer) {
    if let tapped = sender.view as? CirclePerson {
        print("we got it: \(tapped.index)")

You now know "which" face was clicked in your table, screen, stack view or whatever.

It's that easy.


you can use

 - (void)highlightLetter:(UITapGestureRecognizer*)sender {
     UIView *view = sender.view; 
     NSLog(@"%d", view.tag); 
}

view will be the Object in which the tap gesture was recognised


Swift 5

In my case I needed access to the UILabel that was clicked, so you could do this inside the gesture recognizer.

let label:UILabel = gesture.view as! UILabel

The gesture.view property contains the view of what was clicked, you can simply downcast it to what you know it is.

@IBAction func tapLabel(gesture: UITapGestureRecognizer) {

        let label:UILabel = gesture.view as! UILabel

        guard let text = label.attributedText?.string else {
            return
        }

        print(text)
}

So you could do something like above for the tapLabel function and in viewDidLoad put...

<Label>.addGestureRecognizer(UITapGestureRecognizer(target:self, action: #selector(tapLabel(gesture:))))

Just replace <Label> with your actual label name


You can also use "shouldReceiveTouch" method of UIGestureRecognizer

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:     (UITouch *)touch {
     UIView *view = touch.view; 
     NSLog(@"%d", view.tag); 
}    

Dont forget to set delegate of your gesture recognizer.


Here is an update for Swift 3 and an addition to Mani's answer. I would suggest using sender.view in combination with tagging UIViews (or other elements, depending on what you are trying to track) for a somewhat more "advanced" approach.

  1. Adding the UITapGestureRecognizer to e.g. an UIButton (you can add this to UIViews etc. as well) Or a whole bunch of items in an array with a for-loop and a second array for the tap gestures.
    let yourTapEvent = UITapGestureRecognizer(target: self, action: #selector(yourController.yourFunction)) 
    yourObject.addGestureRecognizer(yourTapEvent) // adding the gesture to your object
  1. Defining the function in the same testController (that's the name of your View Controller). We are going to use tags here - tags are Int IDs, which you can add to your UIView with yourButton.tag = 1. If you have a dynamic list of elements like an array you can make a for-loop, which iterates through your array and adds a tag, which increases incrementally

    func yourFunction(_ sender: AnyObject) {
        let yourTag = sender.view!.tag // this is the tag of your gesture's object
        // do whatever you want from here :) e.g. if you have an array of buttons instead of just 1:
        for button in buttonsArray {
          if(button.tag == yourTag) {
            // do something with your button
          }
        }
    }
    

The reason for all of this is because you cannot pass further arguments for yourFunction when using it in conjunction with #selector.

If you have an even more complex UI structure and you want to get the parent's tag of the item attached to your tap gesture you can use let yourAdvancedTag = sender.view!.superview?.tag e.g. getting the UIView's tag of a pressed button inside that UIView; can be useful for thumbnail+button lists etc.


Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

Examples related to objective-c

Adding a UISegmentedControl to UITableView Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Warp \ bend effect on a UIView? Use NSInteger as array index Detect if the device is iPhone X Linker Command failed with exit code 1 (use -v to see invocation), Xcode 8, Swift 3 ITSAppUsesNonExemptEncryption export compliance while internal testing? How to enable back/left swipe gesture in UINavigationController after setting leftBarButtonItem? Change status bar text color to light in iOS 9 with Objective-C

Examples related to uigesturerecognizer

How to call gesture tap on UIView programmatically in swift tap gesture recognizer - which object was tapped? How to disable back swipe gesture in UINavigationController on iOS 7 UITapGestureRecognizer - single tap and double tap UIGestureRecognizer on UIImageView

Examples related to uitapgesturerecognizer

How to make a UILabel clickable? tap gesture recognizer - which object was tapped? UITapGestureRecognizer - single tap and double tap Create tap-able "links" in the NSAttributedString of a UILabel?