Multiple row selection in iPhone table view

In this tutorial I will explain the most powerful feature of UITableView, called multiple selection of rows. Create a new project in Xcode using single window application template and name it as TableViewMultiSelection. Before proceeding further we need to add a navigation controller to the AppDelegate and make ViewController as its root view. We can do this either by adding UINavigationController and its root view in AppDelegate.m file or by using nib file of ViewController class. I am not digging into the details of the navigation code because it is quite common in all applications. Now open ViewController.xib file, add a table view outlet and connect it with the associated outlet in .h file. Open ViewController.h file and modify it as follows.

@interface ViewController : UIViewController<UITableViewDataSource, UITableViewDelegate, UIActionSheetDelegate>

@property (nonatomic, strong) IBOutlet UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *dataArray;
@property (nonatomic, strong) UIBarButtonItem *editButton;
@property (nonatomic, strong) UIBarButtonItem *cancelButton;
@property (nonatomic, strong) UIBarButtonItem *addButton;
@property (nonatomic, strong) UIBarButtonItem *deleteButton;

@end

Multiple selection of rows in UITableView are enabled by adding the following line in ViewDidLoad of ViewController.m file.

self.tableView.allowsMultipleSelectionDuringEditing = YES;

The default value of this property is set to NO. Generally this property returns a boolean value that controls whether users can select more than one cell simultaneously in editing mode. If you set to YES, check marks appear next to selected rows in editing mode. In addition, UITableView does not query for editing styles when it goes into editing mode. If you call indexPathsForSelectedRows, you can get the index paths that identify the selected rows. Now we need to allocate edit, add, cancel and delete bar buttons and its action methods. For that we need to modify the ViewDidLoad method by adding the following lines of code.

self.dataArray = [[NSMutableArray alloc] initWithObjects:@"Item 1",@"Item 2",@"Item 3",@"Item 4",@"Item 5",nil];
self.editButton = [[UIBarButtonItem alloc] initWithTitle:@"Edit" style:UIBarButtonItemStyleBordered target:self action:@selector(editButton:)];
self.cancelButton = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStyleBordered target:self action:@selector(cancelButton:)];
self.addButton = [[UIBarButtonItem alloc] initWithTitle:@"Add" style:UIBarButtonItemStyleBordered target:self action:@selector(addButton:)];
self.deleteButton = [[UIBarButtonItem alloc] initWithTitle:@"Delete" style:UIBarButtonItemStyleBordered target:self action:@selector(deleteButton:)];
self.deleteButton.tintColor = [UIColor redColor];
[self.navigationItem setRightBarButtonItem:self.editButton];
[self.navigationItem setLeftBarButtonItem:self.addButton];

The last two lines of code indicates edit and add buttons are placed in right and left sides of navigation bar respectively. Implement the edit action method as follows.

(void)editButton:(id)sender
{
    self.navigationItem.rightBarButtonItem = self.cancelButton;
    self.deleteButton.title = kDeleteAllTitle;
    self.navigationItem.leftBarButtonItem = self.deleteButton;
    [self.tableView setEditing:YES animated:YES];
}

After taping the edit button, immediately it will turn up as a cancel button. The number of rows in table view will be the length of dataArray object. Modify the cellForRowAtIndexPath method in such a way to display the content of dataArray object based on its index. Following code line will display each rows content.

cell.textLabel.text = [self.dataArray objectAtIndex:indexPath.row];

Build and run the code you will see the following screenshot flow. Screenshot_1 appears as a first screen, if you tap on edit button you will see the screenshot_2 and after selecting first two rows you will see the screenshot_3.

Now we will customize the delete button text to show the number of selected rows as its text. Add the following lines of code on top of ViewController.m file.

static NSString *kDeleteAllTitle = @"Delete All";
static NSString *kDeletePartialTitle = @"Delete (%d)";

Implement didDeselectRowAtIndexPath and didSelectRowAtIndexPath as follows.

(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (self.tableView.isEditing)
    {
        NSArray *selectedRows = [self.tableView indexPathsForSelectedRows];
        self.deleteButton.title = (selectedRows.count == 0) ?
        kDeleteAllTitle : [NSString stringWithFormat:kDeletePartialTitle, selectedRows.count];
    }
}

(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
        if (self.tableView.isEditing)
    {
        NSArray *selectedRows = [self.tableView indexPathsForSelectedRows];
        NSString *deleteButtonTitle = [NSString stringWithFormat:kDeletePartialTitle, selectedRows.count];
       
        if (selectedRows.count == self.dataArray.count)
        {
            deleteButtonTitle = kDeleteAllTitle;
        }
        self.deleteButton.title = deleteButtonTitle;
    }
}

Role of above delegate methods is to modify the text of delete button based on number selected or unselected rows. Finally we ned to implement the action methods of delete and add buttons. In delete button action method, we use UIActionSheet to populate set of options like delete selected rows or cancel the deleted action. And after that we implement UIActionSheet’s delegate method to perform delete or cancel actions by registering its delegate protocol. Delete and add action methods look like this.

(void)deleteButton:(id)sender
{
        NSString *actionTitle = ([[self.tableView indexPathsForSelectedRows] count] == 1) ?
    @"Are you sure you want to remove this item?" : @"Are you sure you want to remove these items?";
    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:actionTitle delegate:self cancelButtonTitle:@"Cancel"
                                               destructiveButtonTitle:@"OK" otherButtonTitles:nil];
     actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
     [actionSheet showInView:self.view];
}

(void)addButton:(id)sender
{
    [self.tableView beginUpdates];
    [self.dataArray addObject:@"New Item"];
    NSArray *paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:(self.dataArray.count 1) inSection:0]];
    [self.tableView insertRowsAtIndexPaths:paths withRowAnimation:NO];
    [self.tableView endUpdates];  
    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(self.dataArray.count 1) inSection:0] atScrollPosition: UITableViewScrollPositionBottom animated:YES];
    self.editButton.enabled = (self.dataArray.count > 0) ? YES : NO;
}

Now build and run the code. You will be able to perform delete action for selected number of rows or we can delete all available rows of table view.

Leave a Reply

Your email address will not be published. Required fields are marked *