Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid swipe to delete calling setEditing at the UITableViewCell

I know, that when I implement tableView:willBeginEditingRowAtIndexPath:and tableView:didEndEditingRowAtIndexPath:, a swipe-to-delete does not call setEditing:animated: at my UITableViewController (being the delegate of the UITableView).

I have a custom UITableViewCell implementation that does a little UI rearrangements when going to edit mode. I wanted to be smart and implemented these changes in setEditing:animated: at the table view cell implementation itself (which obviously makes sense).

However, when swiping to delete, I still get a call to setEditing:animated: at my table view cell implementation. And I have no parameter that tells me that I am swiping. The call stack also shows none of my own methods that would give me a chance to do something. It shows that setEditing:animated is called at the UITableView. The only thing obviously is, that it is not called at the delegate (my controller in this case).

Of course, I could set a flag at the cell in tableView:willBeginEditingRowAtIndexPath: that tells it that the next setEditing call will be for a swipe, but that does not sound like good style.

Edit: it doesn't even work, because it is not guaranteed that tableView:didEndEditingRowAtIndexPath: is called, so I cannot set the flag back.

Any ideas how to solve this issue elegantly?

like image 683
Björn Landmesser Avatar asked Jun 22 '11 09:06

Björn Landmesser


2 Answers

I know this has probably been done to death, but the solutions presented didn't seem to be a complete simple answer, nor did they seem to provide good example code, so I thought I'd add my answer.

Add to your class a private instance variable:

@implementation MyTableViewController {
    BOOL _cellSwiped;
}

Override the setEditing method to look for the _cellSwiped variable and only propagate if we didn't swipe. The part that people seem to be missing is that _cellSwiped needs to be reset back to NO otherwise you will never be able to use the edit button after swiping!

- (void) setEditing:(BOOL)editing animated:(BOOL)animated {
    if (!_cellSwiped) {
        [super setEditing:editing animated:animated];
    } else if (!editing) {
        _cellSwiped = NO;
    }
}

Finally, add this method override to detect the swipe:

- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath {
    _cellSwiped = YES;
}
like image 25
Gujamin Avatar answered Oct 14 '22 19:10

Gujamin


I think UITableViewCell's willTransitionToState: instance method may be what you are looking for. Something like this:

- (void)willTransitionToState:(UITableViewCellStateMask)state
{
    if (state == UITableViewCellStateShowingDeleteConfirmationMask) {
        swipedToDelete = YES; // BOOL ivar
    }
}

- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    if (swipedToDelete) {
        // do your stuff, or don't
    }
}

Is that it?

like image 57
Filip Radelic Avatar answered Oct 14 '22 17:10

Filip Radelic