0

Essentially I would like to be able to select all and deselect all cells in a tableview.

Currently I am using:

for section in 0..<tableView.numberOfSections {
    for row in 0..<tableView.numberOfRows(inSection: section) {
        let indexPath = IndexPath(row: row, section: section)
        _ = tableView.delegate?.tableView?(tableView, willSelectRowAt: indexPath)
        tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
        tableView.delegate?.tableView?(tableView, didSelectRowAt: indexPath)
    }
}

While this function does work it acts as both a select and deselect all, which is not what is needed. Instead I need it to allways select all records and if some records are already selected they should be ignored when this function is executed. It should only select those records not already selected. How can the function above be modified to only select rows not deselect ones that are already selected.

UPDATE:

I do the following in didSelectRow:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    structure[indexPath.row].isSelected.toggle()
    let portfolio = structure[indexPath.row]
    updateSelection(of: portfolio, at: indexPath)
}

The function updateSelection is just a function that updates the API using Alamofire,

John
  • 965
  • 8
  • 16
  • Does this answer your question? [Select all the cells in UITableView](https://stackoverflow.com/questions/1524043/select-all-the-cells-in-uitableview) – manman Nov 08 '19 at 04:46
  • Not exactly, none of those methods watch for cells already selected. If a cell is already marked as selected it should not be touched. – John Nov 08 '19 at 04:47
  • Basically I need it to reject deselection, is that possible? – John Nov 08 '19 at 04:54
  • @JonathanMense so you would like to deselect previously selected rows after selecting all rows? that means suppose you have total 10 rows and out of them you have selected 3 now you are trying to click a button which will select all rows then only 7 rows should be selected and other 3 should be deselected... It is something that you would like to achieve? – Maulik Pandya Nov 08 '19 at 05:46

2 Answers2

1

Just tried following methods in a sample project which worked as you want:

func selectAll() {
    for section in 0..<tableView.numberOfSections {
        for row in 0..<tableView.numberOfRows(inSection: section) {
            let indexPath = IndexPath(row: row, section: section)
            tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
        }
    }
}

func deselectAll() {
    for section in 0..<tableView.numberOfSections {
        for row in 0..<tableView.numberOfRows(inSection: section) {
            let indexPath = IndexPath(row: row, section: section)
            tableView.deselectRow(at: indexPath, animated: false)
        }
    }
}

Is that something that's not working for you?

manman
  • 4,743
  • 3
  • 30
  • 42
  • I’ve been testing your code and I’ve found that it does not work in my case because I also use the checkmark accessory..basically the logic should be the code that I have, but if a checkmark already exist don’t select it. Do you know how this can be done? – John Nov 09 '19 at 02:29
  • Need to see your code, current code doesn't change checkmark, you might have a logic in your cell toggling the checkmark instead of looking into `isSelected` – manman Nov 10 '19 at 22:18
  • Ok, I have added some more details, the updated post shows how I use toggle to switch from a selected state to an unselected state. Does this help? – John Nov 11 '19 at 05:44
  • Then just simply don't use `toggle` and use `= true`. You can also, guard to check if `structure[indexPath.row].isSelected == true` just return and do nothing – manman Nov 12 '19 at 06:14
  • I appreciate your help, can you have a look at my last comment for @vadian answer? I explain some more details about the issue – John Nov 12 '19 at 06:51
0

According to you UPDATE ist seems that there is only one section in the table view so your code is misleading.

A simple solution is to enumerate the data source array and check if isSelected has the desired value. If not toggle the value and update the API. Finally reload the table view. Calling the function with true will select all cells, false will deselect the cells.

func changeSelection(_ flag : Bool) {
    for (index, portfolio) in structure.enumerated() {
        if portfolio.isSelected != flag {
            structure[index].isSelected.toggle()
            updateSelection(of: structure[index], at: IndexPath(row: index, section: 0))
        }
    }
    tableView.reloadData()
}

Side note:

Never call delegate methods containing will, did and should yourself.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • I'm sorry I don't understand where I can choose to have the function only select or only deselect? You mention calling the function with true or false, how can this be done? I need the function to only select all rows, if they are already selected do not deselect them. – John Nov 11 '19 at 11:43
  • Just call `changeSelection(true)` to select all unselected cells and `changeSelection(false)` to deselect all selected cells. – vadian Nov 11 '19 at 11:52
  • The only other issue is the checkmarks are being applied before the record changes, the checkmarks should not appear until change is made in API using the updateSelection function. – John Nov 11 '19 at 13:25
  • The original function I have in my post, does that ...`for section in 0.. – John Nov 11 '19 at 13:26
  • 1) Reload each row after returning from updating the API. 2) As I said according to the code in `didSelect` there is only one section. – vadian Nov 11 '19 at 14:03
  • How can each row be reloaded after updating from API? – John Nov 11 '19 at 14:21
  • I have restructured and improved how I am writing updateSelection to what you have recommended to someone else in a different post [Here](https://stackoverflow.com/questions/58012819/accessories-disappear-when-scrolling-tableview-swift-5). I just don't understand how this can be applied when doing select all – John Nov 11 '19 at 22:14