Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alert before deleting UITableView cell - (UIAlertController) Swift or Objective-C

I want to delete a Table View cell, but before that action happens I want to give the user an alertview. I got this:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Warning"
                                                        message:@"Are you sure?"
                                                       delegate:self
                                              cancelButtonTitle:@"NO"
                                              otherButtonTitles:@"YES", nil];
        [alert show];

        [self.array removeObjectAtIndex:indexPath.row];//or something similar to this based on your data source array structure
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
    if([title isEqualToString:@"Nee"])
    {
        NSLog(@"Nothing to do here");
    }
    else if([title isEqualToString:@"Ja"])
    {
        NSLog(@"Delete the cell");

    }
}

But now when I swipe to right on the cell and the delete button appears I got no AlertView. I only get the AlertView when I press on the delete button. When I press on the delete button the message appears but the cell is already been deleted.

How to make this work? So there is an AlertView when I swipe.

like image 396
user1883396 Avatar asked Jan 12 '13 20:01

user1883396


3 Answers

Regarding the sequence, everything is fine. commitEditingStyle will be called only when the delete button was pressed already. The point is that you are actually removing the object before the alert is responded to. Change it to this:

Add this to the .m file before @implementation:

@interface PutYourViewControllerClassNameHere
@property (strong, nonatomic) NSIndexPath *indexPathToBeDeleted;
@end

And then:

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

        self.indexPathToBeDeleted = indexPath;

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Warning"
                                                        message:@"Are you sure?"
                                                       delegate:self
                                              cancelButtonTitle:@"NO"
                                              otherButtonTitles:@"YES", nil];
        [alert show];
        // do not delete it here. So far the alter has not even been shown yet. It will not been shown to the user before this current method is finished.     
    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    // This method is invoked in response to the user's action. The altert view is about to disappear (or has been disappeard already - I am not sure) 

    NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
    if([title isEqualToString:@"NO"])
    {
        NSLog(@"Nothing to do here");
    }
    else if([title isEqualToString:@"YES"])
    {
        NSLog(@"Delete the cell");

        [self.array removeObjectAtIndex:[self.indexPathToBeDeleted row]];
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:self.indexPathToBeDeleted] withRowAnimation:UITableViewRowAnimationFade];
    }
}

Edit: This should compile, despite minor syntax errors probably. General assupmtion: You are dealing with one section only. At least only with one section within deletions are possible.

like image 54
Hermann Klecker Avatar answered Nov 09 '22 14:11

Hermann Klecker


iOS 8 +

iOS 8 introduced UIAlertController. This allows you to write your delete and cancel code in completion blocks instead of in delegate methods (as per -clickedButtonAtIndex of the old UIAlertView).

Swift 3

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        let alertController = UIAlertController(title: "Warning", message: "Are you sure?", preferredStyle: .alert)

        let deleteAction = UIAlertAction(title: "Delete", style: .destructive, handler: { (action) in
            self.tableView.deleteRows(at: [indexPath], with: .fade)
        })
        alertController.addAction(deleteAction)

        let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
        alertController.addAction(cancelAction)

        present(alertController, animated: true, completion: nil)
    }
}

Objective-C

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Warning" message:@"Are you sure?" preferredStyle:UIAlertControllerStyleAlert];

        UIAlertAction *deleteAction = [UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
            [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
        }];
        [alertController addAction:deleteAction];

        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            NSLog(@"Don't do anything");
        }];
        [alertController addAction:cancelAction];

        [self presentViewController:alertController animated:YES completion:nil];
    }
}
like image 40
MattyG Avatar answered Nov 09 '22 13:11

MattyG


Youre calling the Alert when the deleting action is already taking place....

Put it in:

-(void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Waarschuwing!"
                                                message:@"Weet je zeker dat je het vak: lalaal wilt verwijderen?"
                                               delegate:self
                                      cancelButtonTitle:@"Nee"
                                      otherButtonTitles:@"Ja", nil];
[alert show];
}

That will call the alert when the cell is swiped and before the button is pressed.

like image 29
Dana K Avatar answered Nov 09 '22 13:11

Dana K