开发者

How to avoid swipe to delete calling setEditing at the UITableViewCell

开发者 https://www.devze.com 2023-03-15 01:45 出处:网络
I know, that when I imp开发者_如何学JAVAlement tableView:willBeginEditingRowAtIndexPath:and tableView:didEndEditingRowAtIndexPath:, a swipe-to-delete does not call setEditing:animated: at my UITableVi

I know, that when I imp开发者_如何学JAVAlement 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?


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?


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


What I do is something like this:

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

Then in the

- (void)setEditing:(BOOL)editing animated:(BOOL)animated 

method I simply check to see if the cellSwiped ivar is set and modify the UI accordingly.


This is an old question, but I'm wondering why nobody seems to be aware of the fact that there is a showingDeleteConfirmation property built right into UITableViewCell (since iOS 2.0):

- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    [super setEditing:editing animated:animated];

    BOOL reallyEditing = editing && !self.showingDeleteConfirmation;
    // [...]
}

No need to override -willTransitionToState: and manually keep track of the state.


- (void)tableView:(UITableView *)tableview commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if(editingStyle != UITableViewCellEditingStyleDelete) {
       // add code here

    }
}

When called, this method will perform the following operations

UITableViewCellEditingStyleNone,
UITableViewCellEditingStyleDelete,
UITableViewCellEditingStyleInsert

If you don't want the swipe option you can set the bool variable in the delegate method

- (void)willTransitionToState:(UITableViewCellStateMask)state

willTransitionToState will be called before

commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号