0

Normal selection of cell on uitableview is working fine. But when long press event is called for a cell it selects the previously selected cell again. For example if user selected 1st cell then long press the second cell ,, event for long press is called for the second cell but selection goes back again to first cell.

this is my codes:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];

if (cell == nil) {

    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MyIdentifier"];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    //add longPressGestureRecognizer to your cell
    UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
                                          initWithTarget:self action:@selector(handleLongPress:)];
    //how long the press is for in seconds
    lpgr.minimumPressDuration = 1.0; //seconds
    [cell addGestureRecognizer:lpgr];

}


return cell;
}

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

CGPoint p = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
if (indexPath == nil) {
    NSLog(@"long press on table view but not on a row");
}
else
{
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
    {
        NSLog(@"long press on table view at row %ld", (long)indexPath.row);

        editViewController *editView = [self.storyboard instantiateViewControllerWithIdentifier:@"editView"]; //dont forget to set storyboard ID of you editViewController in storyboard
        [self.navigationController pushViewController:editView animated:YES];
    }
}

}

1 Answers1

1

It seems that the issue you are having is rooted in the fact that marking a cell as selected and handling a long press gesture event on that cell are separate. My interpretation of your question is that you have a table view with single selection (not multiple) and that you want the cells to become 'selected' both via the normal tap to select action and also by recognizing a long press gesture. However -- while you want the cell to become selected with the long press gesture, you would like the longpress to result in a different action than selection via a normal tap (e.g. if the user taps a cell you want to launch view controller A but if the user long presses that cell you want to launch view controller B, and in both cases you want the table to regard the cell as 'selected) ...let me know if what you want is different than this, and I can update the answer.

This isn't a very common behavior for table views, but we can make it work by modifying your code a bit:

First define a property to keep track of whether a long press is happening:

@property (assign, nonatomic) BOOL longPressActive;

Then in your handleLongPress method, tell the table to select the row:

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

    CGPoint p = [gestureRecognizer locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
    if (indexPath == nil) {
        NSLog(@"long press on table view but not on a row");
    }
    else
    {
        if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
        {
            NSLog(@"long press on table view at row %ld", (long)indexPath.row);
            self.longPressActive = YES;

            [self.tableView selectRowAtIndexPath:indexPath
                                        animated:NO
                                  scrollPosition:UITableViewScrollPositionNone];

        }else if (gestureRecognizer.state == UIGestureRecognizerStateEnded ||
                  gestureRecognizer.state == UIGestureRecognizerStateCancelled) {
            self.longPressActive = NO;
    }

}

Finally, in your table view delegate methods, define the behavior you expect after selection. Note that in the is example a long press on any cell will result in the same view controller displaying. In order to set that view controller up differently you can follow a process similar to my answer in your prior question or you can pass row specific data to the editViewController after you instantiate it.

- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    if (self.longPressActive) { //Perform action desired when cell is long pressed

        editViewController *editView = [self.storyboard instantiateViewControllerWithIdentifier:@"editView"];
        [self.navigationController pushViewController:editView animated:YES];

    }else { //Perform action desired when cell is selected normally

        //Your code here
    }

} 

Hopefully that's helpful.

Community
  • 1
  • 1
BFar
  • 2,447
  • 22
  • 23
  • i use TableView to show core data entity, now if the user taps a cell i want to launch EditViewController but if the user long presses that cell i want to launch Details of that cell, so its important that wاich cell is pressed or which cell is long pressed, because i want to pass the selected cell(by press) to EditViewController and slected cell (by Long press) to DetailsViewController – Mostafa Taghipour Aug 28 '14 at 20:51
  • The code above should do this. However, to clarify, you shouldn't be passing the cell to either the EditViewController or the DetailsViewController, you should be passing the reference to your core data entity managed object. Passing the cell itself would break the MVC paradigm. – BFar Aug 28 '14 at 22:57
  • i now that, This is my specific question: How to change Selection of Cell on Long Press? – Mostafa Taghipour Aug 30 '14 at 13:38
  • In `handleLongPress` method in my answer I included the code to inform the table that the cell should become selected: `[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];` Is that not working for you? One thing to note is that calling that method changes the selection state for the cell, but it will not call the `tableView: didSelectRowAtIndexPath:` delegate method...so if you want to call that too, you should do so directly. – BFar Aug 30 '14 at 17:51