14

I'm trying to ignore UITapGestureRecognizer taps on a UITableView with the following:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
      if ([touch.view isKindOfClass:[UITableViewCellContentView class]]) {
          return NO; // ignore the touch
      }
      return YES; // handle the touch
}

It won't compile: "Use of undeclared identifier 'UITableViewCellContentView'

Undocumented class? Need to subclass? Better way to accomplish this?

Thanks for any help.

Jimmy_m
  • 1,568
  • 20
  • 24

5 Answers5

42

This seems to do it:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if([touch.view isKindOfClass:[UITableViewCell class]]) {
         return NO;
    }
    // UITableViewCellContentView => UITableViewCell
    if([touch.view.superview isKindOfClass:[UITableViewCell class]]) {
         return NO;
    }
    // UITableViewCellContentView => UITableViewCellScrollView => UITableViewCell
    if([touch.view.superview.superview isKindOfClass:[UITableViewCell class]]) {
         return NO;
    }
    return YES; // handle the touch
}
Sergio del Amo
  • 76,835
  • 68
  • 152
  • 179
Jimmy_m
  • 1,568
  • 20
  • 24
11

You can do this.

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
    {
        if ([NSStringFromClass([touch.view class]) isEqualToString:@"UITableViewCellContentView"]) {
            return NO;
        }else{
            return YES;
        }
    }
guangxyou
  • 121
  • 1
  • 4
6

I've just came across this problem, and the following solution works on all iOS versions, without having the risk of Apple changing the view hierarchy of the tableView. Basicaly, keep a reference to your UITableView:

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
      if([touch.view isDescendantOfView:detailsTableView]) {
          return NO;
      }
      return YES;
   }

//isDescendantOfView:YES if the receiver is an immediate or distant subview of view or if view is the receiver itself; otherwise NO.
Durican Radu
  • 1,327
  • 11
  • 12
2

Here's the swift solution for the selected answer.

I couldn't use the "MyTableView" named dependency check because I had a custom BaseViewController that many view controllers derive from. Some view controllers have a tableview, some have a collection view or both but in all cases the gesture recognizer steals their touches.

I didn't want to put this gesture handling code in every subclass, so the only way I got it working in the base class is this:

extension BaseViewController: UIGestureRecognizerDelegate {

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
        var view = touch.view
        while view != nil {
            if view!.isKindOfClass(UICollectionView) || view!.isKindOfClass(UITableView) {
                return false
            } else {
                view = view!.superview
            }
        }
        return true
    }

}
Travis M.
  • 10,930
  • 1
  • 56
  • 72
0

I think its clear and simpler to check touch region.

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

    let point = touch.location(in: viewContentContainer)
    return !tableRules.frame.contains(point)
}
Mike Glukhov
  • 1,758
  • 19
  • 18