Jimmy_m
Jimmy_m

Reputation: 1598

shouldReceiveTouch on UITableViewCellContentView

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.

Upvotes: 14

Views: 8513

Answers (5)

Mike Glukhov
Mike Glukhov

Reputation: 1830

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)
}

Upvotes: 0

Travis M.
Travis M.

Reputation: 11257

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
    }

}

Upvotes: 2

guangxyou
guangxyou

Reputation: 121

You can do this.

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

Upvotes: 11

Durican Radu
Durican Radu

Reputation: 1337

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.

Upvotes: 6

Jimmy_m
Jimmy_m

Reputation: 1598

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
}

Upvotes: 42

Related Questions