4

I would like to know when the user applies swipe actions on cells of a UITableView. As per the doc, the UITableViewDelegate methods should I use are the following:

- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath;

The willBegin... is called once while the didEnd... is called twice. Is there any reason for this?

My goal is to know when the user has performed a swipe gesture on a cell, followed by a cancel one (he doesn't want to delete anything). This in order to restore the previous selected cell if no action was performed (as per UITableView loses selection).

Any hints?

Community
  • 1
  • 1
Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
  • 1
    I don't see this behavior. Create a simple table view with minimal functionality. Do you still see this behavior? Perhaps your current code is doing something that is causing the double call. – rmaddy Nov 17 '14 at 15:47
  • @rmaddy I set up a minimal sample code with a UITableView and the behavior persists. This happens on simulator. I'll try on device. Thanks. – Lorenzo B Nov 17 '14 at 15:50
  • @rmaddy the problem is confined to simulator. I'm currently using 8.1. Strange enough. – Lorenzo B Nov 17 '14 at 15:55
  • I take it back. Under iOS 8.1 (at least) I'm seeing two calls to `didEndEditing`. This is on a real device. I have a table view with one row. I did a swipe-to-delete. `willBeginEditing` was called. The Delete button appeared. I then tapped on the table view outside the row and `didEndEditing` is called twice. I wonder if this is an iOS 8 issue. – rmaddy Nov 17 '14 at 16:00
  • @rmaddy I'm running an iOS 7 device where source code was compiled with iOS 8.1 and xCode 6.1. I'm seeing only one call. I did not try with a iOS 8 device. I should upload a radar. – Lorenzo B Nov 17 '14 at 16:03
  • I just reran my same test on a device with iOS 7.1.2 and `didEndEditing` is only called once. So it appears to be an iOS 8 issue. – rmaddy Nov 17 '14 at 16:12
  • Thanks @rmaddy for the confirmation. If you want to add your reply below, I will be happy to mark it as the correct answer. In next days I will open a radar. – Lorenzo B Nov 17 '14 at 16:13

2 Answers2

3

My solution is described in my blog Restore the selection of a UITableViewCell after cancelling the “Swipe to delete” operation (Dec 22nd, 2014). To summarize, use a boolean value that keeps track of operations.

I opened a radar. I will wait for a reply and I will update with the feedback.

func tableView(tableView: UITableView, willBeginEditingRowAtIndexPath indexPath: NSIndexPath) {

    self.swipeGestureStarted = true
}

func tableView(tableView: UITableView, didEndEditingRowAtIndexPath indexPath: NSIndexPath) {
    if(self.swipeGestureStarted) {
        self.swipeGestureStarted = false

        self.tableView.selectRowAtIndexPath(self.selectedIndexPath, animated: true, scrollPosition: .None)
    }
}
Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
2

I encountered this problem too, and was able to solve it by declaring a BOOL as a member to my view controller:

@interface ViewController ()

@property (nonatomic, assign) BOOL isEditingRow;

@end

@implementation ViewController

...

... and then setting and reading the value of the BOOL in the UITableView's delegate methods:

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

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

        // now do processing that you want to do once - not twice!
    }
}

It's more of a workaround, but very frustrating that this occurs at all.

Luke
  • 11,426
  • 43
  • 60
  • 69