Mac Catalyst: tableView allowmultipleselection not working

Multiple selection on macOS Catalyst does not work in quite the same way as on iOS and iPadOS and this appears to be either a bug or an unfortunate choice of intended behavior.

On macOS Catalyst, if you have enabled multiple selection in edit mode by setting tableView.allowsMultipleSelectionDuringEditing to true, only one row at a time can be directly selected by clicking with the pointer. However, multiple selection of contiguous rows is enabled by selecting a first row and then holding down SHIFT while selecting a second row, and multiple selection of non-contiguous rows is enabled by selecting a first row and then holding down COMMAND while selecting additional rows. This is Mac-like behavior in that it is how multiple selection generally works on macOS. So it is possible that this was intended behavior. But if that is the case, it is behavior that is hard to discover, not what an iOS/iPadOS user might expect, and works differently than on iOS and iPadOS. And it causes other problems - for example, in code I have a "Select All" function that is able to select all rows from code on iOS/iPadOS, and this code doesn't work on macOS Catalyst.

I filed Feedback on this. There is a simple project on GitHub at WB2ISS/MultipleSelection that demonstrates the problem.


While everything that was said here is true, there is an 'easy' way to hack this behaviour. With the code below you will get the same behaviour on Mac as on iOS/iPadOS

#if targetEnvironment(macCatalyst)
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    if let selectedRows = tableView.indexPathsForSelectedRows, selectedRows.contains(indexPath) {
        tableView.deselectRow(at: indexPath, animated: false)
        return nil
    }
    return indexPath
}

func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath? {
    if let selectedRows = tableView.indexPathsForSelectedRows, selectedRows.contains(indexPath) {
        return nil
    }
    return indexPath
}

func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
    // the mac sets isHighlighted of each other cell to false before selecting them again which leads to a flickering of the selection. Therefore go through the selected cells and highlight them here manually
    tableView.indexPathsForSelectedRows?.forEach { tableView.cellForRow(at: $0)?.isHighlighted = true }
    return true
}
#endif