UITableView Multiple Selection

In your implementation of -tableView:didSelectRowAtIndexPath: you would set the table view cell's accessoryType property depending on its current value (so it would toggle on and off with multiple taps). For example:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)path {
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:path];

    if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
        cell.accessoryType = UITableViewCellAccessoryNone;
    } else {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
}

You could either maintain an array of selected states in addition to the cells' own accessory type state, or iterate over the cells in the table view querying for each one's state in order to read out the selected rows.


For multiple selection, add the line below in viewDidLoad()

tableView.allowsMultipleSelection = true

Configure each cell after dequeuing (or initializing) it in tableView(_:cellForRowAt:)

let selectedIndexPaths = tableView.indexPathsForSelectedRows
let rowIsSelected = selectedIndexPaths != nil && selectedIndexPaths!.contains(indexPath)
cell.accessoryType = rowIsSelected ? .checkmark : .none
// cell.accessoryView.hidden = !rowIsSelected // if using a custom image

Update each cell when it's selected/deselected

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let cell = tableView.cellForRow(at: indexPath)!
    cell.accessoryType = .checkmark
    // cell.accessoryView.hidden = false // if using a custom image
}

override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    let cell = tableView.cellForRow(at: indexPath)!
    cell.accessoryType = .none
    // cell.accessoryView.hidden = true  // if using a custom image
}

When you're done, get an array of all the selected rows

let selectedRows = tableView.indexPathsForSelectedRows

and get the selected data, where dataArray maps to the rows of a table view with only 1 section

let selectedData = selectedRows?.map { dataArray[$0.row].ID }