Search code examples
objective-ccocoa-touchuitableviewios7uiactionsheet

How do I detect the tap of a UIActionSheet button called inside a table view delegate method?


Ok I have a tableView with a UIActionSheet within it and there is no segue or anything a long those lines. A user has the option to swipe and delete a row or another option to take the user represented by a row a offline again.

When a user swipes they can delete the row. When a user taps a UIActionsheet pops up with the option to "Take Offline" (destructive button) or cancel.

enter image description here

This is all wrapped in a tableView delegate method:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    NSLog(@"%d", [indexPath row]);

    Person *person = [people objectAtIndex:indexPath.row];

    UIActionSheet *popup = [[UIActionSheet alloc] initWithTitle:[NSString stringWithFormat:@"Need to edit %@'s info?", person.name]
                                                       delegate:self
                                              cancelButtonTitle:@"Cancel"
                                         destructiveButtonTitle:@"Take Offline"
                                              otherButtonTitles:nil, nil];
   [popup showInView:tableView];
   [popup addButtonWithTitle:@"Cancel"];


     [people removeObjectAtIndex:[indexPath row]];
    [tableView reloadData];
}

I would normally use a UIActionSheetDelegate method to detect the tap of a button.

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {

    if (buttonIndex == 1) {
        NSLog(@"Button 1 was clicked");
    }

}

The problem I'm having is when I tap a row in my table the object is removed from the array and the table is reloaded instantly.

I don't want this to happen until the "Take Offline" button is clicked but can't figure out a way to do this. I've tried a future such as storing objects in instance variables and accessing them from other methods and trying to execute the code out of the tableView method but keep confusing myself.

What is the best way to do this?

Kind regards


Solution

  • I have written a blog post about how to (and why) add block callbacks to alert views, action sheets and animations:

    http://blog.innovattic.com/uikitblocks/

    Using this approach you don't have to use a delegate and can instead rewrite your tableView:didSelectRowAtIndexPath: method like so:

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        NSLog(@"%d", [indexPath row]);
    
        Person *person = [people objectAtIndex:indexPath.row];
    
        UIActionSheet *popup = [[UIActionSheet alloc] initWithTitle:[NSString stringWithFormat:@"Need to edit %@'s info?", person.name]
                                                  cancelButtonTitle:@"Cancel"
                                             destructiveButtonTitle:@"Take Offline"
                                                  otherButtonTitles:nil, nil];
    
        [popup setHandler:^(UIActionSheet *sheet, NSInteger buttonIndex) {
            [people removeObjectAtIndex:[indexPath row]];
            [tableView reloadData];
        } forButtonAtIndex:[popup destructiveButtonIndex]];
    
        [popup showInView:tableView];
    }
    

    You can download the source files for this from GitHub:

    https://github.com/Innovattic/UIKit-Blocks