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?
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.
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.
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
}
Swift Version:
override func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
if(do something){
return UITableViewCellEditingStyle.Delete or UITableViewCellEditingStyle.Insert
}
return UITableViewCellEditingStyle.None
}
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.
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
.
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
}
}
Success story sharing