1

I'm trying to delete rows, delete sections and reload rows simultaneously. I made a simple app to demonstrate my crash. It starts with 3 sections. When buttonPressed is called, sections 0 and 1 are removed from data, then performBatchUpdates is called to update the table view.

class ViewController: UIViewController {

    @IBOutlet var tableView: UITableView!

    var data: [[String]] = [
        ["0-0"],
        ["1-0"],
        ["2-0",
         "2-1",
         "2-2"],
    ]

    @IBAction func buttonPressed(_ sender: UIButton) {
        data = [
            ["2-0 new",
             "2-1 new",
             "2-2 new"],
        ]

        tableView.performBatchUpdates({
            self.tableView.deleteRows(at: [
                  IndexPath(row: 0, section: 0),
                  IndexPath(row: 0, section: 1),
              ], with: .automatic)

            self.tableView.reloadRows(at: [
                IndexPath(row: 0, section: 2),
                IndexPath(row: 1, section: 2),
                IndexPath(row: 2, section: 2),
            ], with: .automatic)

            self.tableView.deleteSections(IndexSet([0, 1]), with: .automatic)

        }, completion: nil)
    }
}

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        return data.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data[section].count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = data[indexPath.section][indexPath.row]
        return cell
    }
}

I get the following row/section accounting exception, but I don't understand where some of the numbers are coming from:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (3) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (2 inserted, 3 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'

JimmyB
  • 326
  • 3
  • 12
  • Your update's don't make sense - You say you are deleting sections 0,1 but you are actually deleting section 1 & 2. That aside, the error is correct; You have deleted row 0 from section 0, but at the end of it all your array contains 3 rows in section 0. – Paulw11 Feb 18 '20 at 03:19
  • Thanks for the reply! `self.tableView.deleteSections(IndexSet([0, 1]), with: .automatic)` will delete sections 0, 1 right? – JimmyB Feb 18 '20 at 03:25
  • Right, but your outer array only contains 1 inner array when you update it, so it contains section 0, not section 2. You can't have section 2 without also having sections 0 & 1. – Paulw11 Feb 18 '20 at 03:29
  • `reloadRows` (like `deleteRows`) acts on the index paths before the update – JimmyB Feb 18 '20 at 03:30
  • Regardless, your updates aren't consistent as after the block is complete section 0 re-appears – Paulw11 Feb 18 '20 at 03:36
  • Absolutely! After the block there is a section 0 -- there is only a single section. But within performBatchUpdates the docs explicitly say that delete and reload indexing references the state of the table view before the update. Or perhaps I've misunderstood the docs: https://developer.apple.com/documentation/uikit/uitableview/1614935-reloadrows – JimmyB Feb 18 '20 at 03:39
  • In addition, it is perfectly valid to just remove sections 0 and 1 without first removing the rows. If you do that, the crash no longer appears. – JimmyB Feb 18 '20 at 03:41
  • The crash also disappears if the 3rd section has only a single row in it before and after the update -- this shows that references in `reloadRows` to `section: 2` are indeed correct. – JimmyB Feb 18 '20 at 04:04
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/208025/discussion-between-paulw11-and-jimmyb). – Paulw11 Feb 18 '20 at 07:50

0 Answers0