UITableView disable swipe to delete, but still have delete in Edit mode?
Asked Answered
C

7

98

I want something similar as the Alarm app, where you can't swipe delete the row, but you can still delete the row in Edit mode.

When commented out tableView:commitEditingStyle:forRowAtIndexPath:, I disabled the swipe to delete and still had Delete button in Edit mode, but what happens when I press the Delete button. What gets called?

Cane answered 9/6, 2009 at 10:42 Comment(0)
C
294

Ok, it turns out to be quite easy. This is what I did to solve this:

Objective-C

- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Detemine if it's in editing mode
    if (self.tableView.editing)
    {
        return UITableViewCellEditingStyleDelete;
    }

    return UITableViewCellEditingStyleNone;
}

Swift 2

override func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
    if tableView.editing {
         return .Delete
    }

    return .None
}

Swift 3

override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
    if tableView.isEditing {
        return .delete
    }

    return .none
}

You still need to implement tableView:commitEditingStyle:forRowAtIndexPath: to commit the deletion.

Cane answered 9/6, 2009 at 15:27 Comment(5)
bu then swipe to delete is automatically enabled, again. Or not?Mattias
No, swipe to delete doesn't get enabled, if it's not in editing mode. That's why I return UITableViewCellEditingStyleNone as default.Cane
Forgot mention that you need if (editingStyle == UITableViewCellEditingStyleDelete) in commitEditingStyle:Cane
Ok, with this statement you got delete action but it has different visuality. Is there any chance to have that action with same visuality of swipe version?Hypoderma
@giuseppe It doesn't matter. He's not wrong by referring back to the self. That delegate method is referring back to the same tableView so he is fine to use either or.Patriciate
B
11

Just to make things clear, swipe-to-delete will not be enabled unless tableView:commitEditingStyle:forRowAtIndexPath: is implemented.

While I was in development, I didn't implement it, and therefore swipe-to-delete wasn't enabled. Of course, in a finished app, it would always be implemented, because otherwise there would be no editing.

Bran answered 7/3, 2011 at 21:16 Comment(0)
E
6

You need to implement the CanEditRowAt function.

You can return .delete in the EditingStyleForRowAt function so you can still delete in editing mode.

func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    if tableView.isEditing {
        return true
    }
    return false
}

func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
    return .delete
}
Ednaedny answered 17/12, 2018 at 10:3 Comment(0)
H
4

Swift Version:

override func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {

    if(do something){

        return UITableViewCellEditingStyle.Delete or UITableViewCellEditingStyle.Insert

    }
    return UITableViewCellEditingStyle.None

}
Hochman answered 25/6, 2015 at 3:2 Comment(0)
M
3

Basically, you enable or disable editing using the methods

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

If editing is enabled, the red deletion icon appears, and a delete conformation requested to the user. If the user confirms, the delegate method

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

is notified of the delete request. If you implement this method, then swipe to delete is automatically made active. If you do not implement this method, then swipe to delete is not active, however you are not able to actually delete the row. Therefore, to the best of my knowledge, you can not achieve what you asked for, unless using some undocumented, private APIs. Probably this is how the Apple application is implemented.

Mattias answered 9/6, 2009 at 15:0 Comment(1)
I solved this by return the UITableViewCellEditingStyleDelete in tableView: editingStyleForRowAtIndexPath: if it's in editing mode.Cane
S
1

On C#:

I had the same issue where it was needed to enable/disable rows with Delete option on swipe. Multiple rows needed to be swiped left and get deleted, keep them in another colour. I achieved using this logic.

[Export("tableView:canEditRowAtIndexPath:")]
public bool CanEditRow(UITableView tableView, NSIndexPath indexPath)
{

    if (deletedIndexes.Contains(indexPath.Row)){
        return false;
    }
    else{
        return true;
    }

}

Note that deletedIndexes are a list of indexes which are deleted from the table without duplicates. This code check whether a row is deleted, then it disables swipe or vice versa.

The equivalent delegate function is Swift is canEditRowAtIndexPath.

Saki answered 17/5, 2018 at 9:30 Comment(0)
A
1

I came across this problem either and fixed with codes below. hope it will help you.

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {

    BOOL deleteBySwipe = NO;
    for (UIGestureRecognizer* g in tableView.gestureRecognizers) {
        if (g.state == UIGestureRecognizerStateEnded) {
            deleteBySwipe = YES;
            break;
        }
    }

    if (deleteBySwipe) {
        //this gesture may cause delete unintendedly
        return;
    }
    //do delete
}

}

Adorne answered 11/7, 2019 at 7:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.