Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swipe to delete cell does not cancel UIButton action

My UITableView has the swipe to delete feature enabled. Each cell has a UIButton on it that performs an action (in this case, perform a segue).

I'd expect that if I swipe the cell by touching the button, the button's action would be canceled/ignored, and only the swipe would be handled. What actually happens, however, is that both gestures (swipe + tap) are detected and handled.

This means that if I just want to delete one cell and "accidentally" swipe by touching the button, the app will go to the next screen.

How can I force my app to ignore the taps in this case?

like image 974
Guilherme Avatar asked May 16 '14 19:05

Guilherme


3 Answers

One elegant way would be to ignore button taps as long as a cell has entered editing mode. This works because the swipe to delete gesture will cause willBeginEditingRowAtIndexPath to be called before the button tap action is invoked.

- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
    self.isEditing = YES;
}

- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
    self.isEditing = NO;
}

// button tapped
- (IBAction)tap:(id)sender
{
    if (self.isEditing) {
        NSLog(@"Ignore it");
    }
    else {
        NSLog(@"Tap");
        // perform segue
    }
}
like image 36
augustzf Avatar answered Sep 28 '22 14:09

augustzf


It's possible to do it also in your cell's subclass:

override func setEditing(editing: Bool, animated: Bool) {
    super.setEditing(editing, animated: animated)

    actionButton?.userInteractionEnabled = !editing
}
like image 23
Anton Plebanovich Avatar answered Sep 28 '22 15:09

Anton Plebanovich


august's answer was nice enough for me, but I figured out how to make it even better:

Checking if the table was on edit mode to decide if the button should perform its action will make it behave as it should, but there will still be an issue in the user experience:

If the user wants to exit the editing mode, he should be able to tap anywhere in the cell to achieve that, including the button. However, the UIButton's action is still analyzed first by the app, and tapping the button will not exit editing mode.

The solution I found was to disable the button's user interaction while entering edit mode, and reenabling it when it's done:

// View with tag = 1 is the UIButton in question
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath {
  [(UIButton *)[[tableView cellForRowAtIndexPath:indexPath] viewWithTag:1] setUserInteractionEnabled:NO];
}

- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath {
  [(UIButton *)[[tableView cellForRowAtIndexPath:indexPath] viewWithTag:1] setUserInteractionEnabled:YES];
}

This way, dragging the button to enter edit mode will not trigger the button's action, and taping it to exit edit mode will indeed exit edit mode.

like image 124
Guilherme Avatar answered Sep 28 '22 15:09

Guilherme