1

I'm got a tableview that displays custom view cells. In viewWillAppear i've setup a long press gesture recognizer that is on the UITableView. My long press is firing and displaying the info about the cell that has been long pressed upon. However when I let go of the press the didSelectRowAtIndexPath method is firing. Is there a way to cancel the touch after the long press fires, so that the select row doesn't get triggered?

I've seen didSelectRowAtIndexPath called after long press and that question does not seem to have an adequate answer as to how to fix the problem.

@implementation ViewController
UILongPressGestureRecognizer *lpgr;
.
.
.

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];

    // setup long press

    lpgr = [[UILongPressGestureRecognizer alloc]
                                          initWithTarget:self action:@selector(handleLongPress:)];
    lpgr.minimumPressDuration = 0.5; //seconds
    lpgr.delegate = self;
    lpgr.cancelsTouchesInView = true;
    [self.myTableview addGestureRecognizer:lpgr];
    [self.myTableview.panGestureRecognizer requireGestureRecognizerToFail:lpgr]; ...
.
.
.

-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{

    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {

        CGPoint p = [gestureRecognizer locationInView:self.myTableview];

        NSIndexPath *indexPath = [self.myTableview indexPathForRowAtPoint:p];
        if (indexPath == nil) {
            NSLog(@"long press on table view but not on a row");
        } else {
            UITableViewCell *cell = [self.myTableview cellForRowAtIndexPath:indexPath];
            CensusData *currentUser;
            if(self.isFiltered){
                currentUser = (CensusData*)[self.filteredTableData objectAtIndex:indexPath.row];
            }else{
                currentUser = (CensusData*)[self.dataArray objectAtIndex:indexPath.row];
            }
            NSLog(@"CURRENT ROW WITH LONG PRESS: %@", currentUser.friendlyName);

        }
    }
}
.
.
.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}
Community
  • 1
  • 1
propstm
  • 3,461
  • 5
  • 28
  • 41
  • can you elaborate more on the handleLongPress: selector. Usually the problem is the other way round: The Gesturerecognizer steals all the touches :-) http://stackoverflow.com/questions/4885693/how-do-you-stop-uitapgesturerecognizer-from-catching-every-tap – thst Feb 27 '17 at 17:21

2 Answers2

2

While the gesture is active (begun but not ended) disable selection on the table view...

- (void)handleLongPress:(UILongPressGestureRecognizer *)gr {
    if (gr.state == UIGestureRecognizerStateBegan) {
        self.myTableview.allowsSelection = NO;
    } else if (gr.state == UIGestureRecognizerStateEnded) {
        self.myTableview.allowsSelection = YES;
    }
}

No need to set the delegate, set cancelsTouches, or implement shouldRecognize... (unless you need these for something else).

EDIT This vc is a minimally complete test. It requires a storyboard with a table view wired to the outlet and the vc as the datasource and delegate...

#import "ViewController.h"

@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@property(weak,nonatomic) IBOutlet UITableView *tableView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    UILongPressGestureRecognizer *gr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
    [self.tableView addGestureRecognizer:gr];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 50;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:@"Row %ld", indexPath.row];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"selected %@", indexPath);
}

- (void)handleLongPress:(UILongPressGestureRecognizer *)gr {
    if (gr.state == UIGestureRecognizerStateBegan) {
        NSLog(@"long press began");
        self.tableView.allowsSelection = NO;
    } else if (gr.state == UIGestureRecognizerStateEnded) {
        NSLog(@"long press ended");
        self.tableView.allowsSelection = YES;
    }
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
danh
  • 62,181
  • 10
  • 95
  • 136
  • I've tried adding the code to disable/reenable selection. This is not working. It would seem to reason that this disables selection for touches after the one triggering the long press and as a result the click, not the touch itself. – propstm Feb 28 '17 at 14:35
  • Hmm. Surprised to hear that. I tested this before answering. Should I post the whole class? – danh Feb 28 '17 at 14:38
  • Please. I'm also building this table out in a sample project, removed from everything else to try to determine if something else is causing this functionality/issue – propstm Feb 28 '17 at 14:48
  • 1
    Added a little test, but discovered something important: my long press and selection work independently even if I leave the allowsSelection property alone. This seems to indicate that you might be doing other manipulation of the tableview's grs that's causing a selection. – danh Feb 28 '17 at 15:20
  • Ok this is really frustrating, it looks like the culprit is the fact that I'm using a subclass of SWTableviewCell, that particular cocoapod hadn't been updated in two years and is what is causing the click to keep propagating through. Because of that this question becomes irrelevant so I'll just delete this question. – propstm Feb 28 '17 at 17:51
0

You can disable tableview then only longGesture is working properly

UILongPressGestureRecognizer* longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPress:)];
[self.myTableview addGestureRecognizer:longPressRecognizer];



-(void)onLongPress:(UILongPressGestureRecognizer*)pGesture
{

    if (pGesture.state == UIGestureRecognizerStateRecognized)
    {
        //Do something to tell the user!
    }
    if (pGesture.state == UIGestureRecognizerStateEnded)
    {
        CGPoint p = [pGesture locationInView:self.myTableview];

        NSIndexPath *indexPath = [self.myTableview indexPathForRowAtPoint:p];

    }

}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
   if ([touch.view isDescendantOfView:self.myTableview]) {

      // Don't let selections of auto-complete entries fire the
      // gesture recognizer
      return NO;
   }

   return YES;

}
propstm
  • 3,461
  • 5
  • 28
  • 41
Rajesh Dharani
  • 285
  • 4
  • 20