propstm
propstm

Reputation: 3629

How do I cancel touches after long press?

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

Upvotes: 1

Views: 1405

Answers (2)

danh
danh

Reputation: 62676

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

Upvotes: 3

Rajesh Dharani
Rajesh Dharani

Reputation: 285

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;

}

Upvotes: 0

Related Questions