Search code examples
iosswiftuitableviewtableviewdelete-row

Tableview deleting rows and sections


I've implemented the following deleting mechanism: on delete action tableView deletes selected rows and if section does not have any rows it will be deleted.

My mechanism looks like this:

guard let selectedRows = self.tableView.indexPathsForSelectedRows,
      let indexPath = self.tableView.indexPathForSelectedRow else { return }
                
self.tableView.beginUpdates()
self.dataSource[indexPath.section].rows.remove(at: indexPath.item)
                
if self.dataSource[indexPath.section].rows.isEmpty {
    self.dataSource.remove(at: indexPath.item)
    self.tableView.deleteSections(IndexSet(arrayLiteral: indexPath.section), with: .fade)
}
                
self.tableView.deleteRows(at: selectedRows, with: .fade)
self.tableView.endUpdates()

My dataSource object:

struct DataSource {
    var section:String
    var rows:[Row]
}

struct Row {
    var data:String
}

The problem is when I select more than one row and try to delete selected rows I've got a crush with following message:

Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (5) must be equal to the number of rows contained in that section before the update (6), plus or minus the number of rows inserted or deleted from that section (0 inserted, 2 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'

While I delete by one row my mechanism works fine, as expected. Even deletes an empty section. Any thoughts, where am I wrong? Thanks a lot.


Solution

  • Solution: just add inverted indexPath array. let invertedIndexPathes = selectedRows.sorted(by: >)

    Fixed mechanism:

    guard let selectedRows = self.tableView.indexPathsForSelectedRows,
           let indexPath = self.tableView.indexPathForSelectedRow else { return }
    
    let invertedIndexPathes = selectedRows.sorted(by: >)
    self.tableView.beginUpdates()
                
    for itemIndexPath in invertedIndexPathes {
        self.dataSource[itemIndexPath.section].rows.remove(at: itemIndexPath.row)
        self.tableView.deleteRows(at: [itemIndexPath], with: .fade)
        self.tableView.reloadData()
    }
                
    if self.dataSource[indexPath.section].rows.isEmpty {
        self.dataSource.remove(at: indexPath.item)
        self.tableView.deleteSections(IndexSet(arrayLiteral: indexPath.section), with: .fade)
    }
                
    self.tableView.endUpdates()