Awais Hussain
Awais Hussain

Reputation: 98

Possible reasons why UIGestureRecognizer is not firing?

I have a subclassed UIView, let's call it TileView.m/h.

In TileView.m, I have the following code: ([setup] is definitely being called, I checked with breakpoints).

- (void)setup {
    self.userInteractionEnabled = YES;
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(testPressed:)];
    [self addGestureRecognizer:tap];
}

- (void)testPressed:(UITapGestureRecognizer *)sender {
    NSLog(@"tap pressed");
}

For some reason, the testPressed method is not called when I tap the view!

Strangely, if I copy the TileView class into a blank xCode project and set it up there, everything works absolutely fine. This is peculiar since gestures are handled first by subviews and then by superviews - so the tile class shouldn't be affected by its superviews. Also the gesture is fully contained within the TileView class.

For reference, the tile view is nested fairly deeply in a: Controller -> controller's view -> scroll view -> container view -> tile view pattern.

I have tried without success:

No luck :/

Any ideas for what else could be going wrong? Or what tests can I run to understand the problem in more detail?

EDIT: More details

Recall that the tile view is nested in: Controller -> controller's view -> scroll view -> container view -> tile view

If I add a gesture recognizer in the controller file with:

[self.view addGestureRecognizer:tap]

and then use [self.view hitTest:[sender locationInView:self.view] withEvent:nil]; in the event handler, I can see that the returned view is a UIScrollView and not a TileView as would be expected.

Additionally, adding the gesture recognizer to self.scrollView instead works fine, but stops working if I add it to self.containerView (which is the only subview of scrollView). containerView has userInteractionEnabled = YES.

Upvotes: 1

Views: 2830

Answers (3)

almas
almas

Reputation: 7187

The reason why its not firing is because you are not keeping a reference to your UITapGestureRecognizer. As soon as setup function returns your UITapGestureRecognizer gets deallocated. If you want it to work save it to a property:

@property (strong, nonatomic) UITapGestureRecognizer *tapRecognizer;

- (void)setup {
    self.tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self 
                                                         action:@selector(testPressed:)];
    [self addGestureRecognizer:self.tapRecognizer];
}

- (void)testPressed:(UITapGestureRecognizer *)sender {
    NSLog(@"tap pressed");
}

Upvotes: 0

eremzeit
eremzeit

Reputation: 4516

You might also want to check that you're not trying to reuse the UITapGestureRecognizer object for different views.

It seems like it's possible because you're just appending the gesture to the view, but in ultimately the view needs to be assigned to the view property on the gesture object so adding the gesture object to a second view will just overwrite the first.

Upvotes: 0

Mundi
Mundi

Reputation: 80265

If the view contains subviews that are UIImageViews, remember that you have to explicitly set the userInteractionEnabled to YES (the default is NO).

If not, the image views will prevent the tap from reaching the superview.

Also, remember to set the number of touches.

Upvotes: 9

Related Questions