How get UITableView IndexPath from UITableView iph

2019-02-26 06:40发布

问题:

In my iPhone app I have one messaging screen. I have added UITapGestureRecognizer on the UIViewController and also I have a UITableview on the screen. I want to select the UITableViewCell but I can't select the UITableView because of UITapGestureRecognizer. When I touch the screen, only the tap gesture action is called but UITableView delegate didSelectRowAtIndexPath: is not called. Could anyone please help me to work on both tap gesture and UITableView:didSelectRowAtIndexPath:. Thanks in advance.

回答1:

While I prefer Matt Meyer's suggestion or my other suggestion of using a custom gesture recognizer, another solution, not involving custom gesture recognizers, would be to have your tap gesture recognizer identify whether you tapped on a cell in your tableview, and if so, manually invoke didSelectRowAtIndexPath, e.g.:

- (void)handleTap:(UITapGestureRecognizer *)sender
{
    CGPoint location = [sender locationInView:self.view];

    if (CGRectContainsPoint([self.view convertRect:self.tableView.frame fromView:self.tableView.superview], location))
    {
        CGPoint locationInTableview = [self.tableView convertPoint:location fromView:self.view];
        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:locationInTableview];
        if (indexPath)
            [self tableView:self.tableView didSelectRowAtIndexPath:indexPath];

        return;
    }

    // otherwise proceed with the rest of your tap handling logic
}

This is suboptimal because if you're doing anything sophisticated with your tableview (e.g. in cell editing, custom controls, etc.), you lose that behavior, but if you're just looking to receive the didSelectRowAtIndexPath, then this might do the job. The other two approaches (separate views or the custom gesture recognizer) let you retain the full tableview functionality, but this could work if you just need something simple and you don't need the rest of the tableview's built-in capabilities.



回答2:

You can use the TagGesture delegate:

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

    return YES;
}

Hope this helps.



回答3:

An easier way to do this is to have two views: one containing the view that you want the tap gesture to be on, and one containing the tableview. You can attach the UITapGestureRecognizer to the view you want it to work on, and then it won't block your UITableView.



回答4:

Assuming you want the tap gesture to work everywhere except over the tableview, you could subclass the tap gesture recognizer, creating a recognizer that will ignore any subviews included in an array of excludedViews, preventing them from generating a successful gesture (thus passing it on to didSelectRowAtIndexPath or whatever):

#import <UIKit/UIGestureRecognizerSubclass.h>

@interface MyTapGestureRecognizer : UITapGestureRecognizer
@property (nonatomic, strong) NSMutableArray *excludedViews;
@end

@implementation MyTapGestureRecognizer

@synthesize excludedViews = _excludedViews;

- (id)initWithTarget:(id)target action:(SEL)action
{
    self = [super initWithTarget:target action:action];
    if (self)
    {
        _excludedViews = [[NSMutableArray alloc] init];
    }

    return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];

    CGPoint location = [[touches anyObject] locationInView:self.view];

    for (UIView *excludedView in self.excludedViews)
    {
        CGRect frame = [self.view convertRect:excludedView.frame fromView:excludedView.superview];

        if (CGRectContainsPoint(frame, location))
            self.state = UIGestureRecognizerStateFailed;
    }
}

@end

And then, when you want to use it, just specify what controls you want to exclude:

MyTapGestureRecognizer *tap = [[MyTapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
[tap.excludedViews addObject:self.tableView];
[self.view addGestureRecognizer:tap];