1

I am facing crash while inserting cells in TableView. I have tried below links but not sure what is the issue

Link1 Link2 Link3 and many

Below is my code

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return names.count 

}

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

Data Source code is below

   private var names: [String] = (50...99).map { String($0) }


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
            self.appendCells()
        }

    }

    private func appendCells() {

        names = (0...49).map { String($0) } + names
        customTableView.beginUpdates()
        let indexPat = IndexPath(row: names.count - 1, section: 0)
        customTableView.insertRows(at: [indexPat], with: .fade)
        customTableView.endUpdates()

    }

I cant understand what am I missing here. Sorry if I am doing foolish. Please let me know If I have to explain more.

I am getting error :

reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (100) must be equal to the number of rows contained in that section before the update (50),

Gagan_iOS
  • 3,638
  • 3
  • 32
  • 51
  • As always, `beginUpdates / endUpdates` is pointless for a single `insert`/`delete`/`move` operation. – vadian Apr 30 '18 at 14:07

4 Answers4

4

The problem is the mismatch in the number of values you add to the data model and the number of rows you add to the table view.

The line:

names = (0...49).map { String($0) } + names

adds 50 new values to your data model.

But you then only tell the table view that there is one new row. This is what you are being told in the error message.

You need a loop to build up an array of 50 index paths.

private func appendCells() {
    names = (0...49).map { String($0) } + names
    var paths = [IndexPath]()
    for row in 0...49 {
        let indexPath = IndexPath(row: row, section: 0)
        paths.append(indexPath)
    }
    customTableView.insertRows(at: paths, with: .fade)
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
0

The error clearly states that you are adding indexPath with row = 99, section = 0, while in reality, it's biggest indexpath holds values: row = 49, section = 0.

Before insertion, tableview calls datasource method numberOfRowsInSection - this method must return your newer, bigger array count (100), not the earlier one (50).

Nirav Bhatt
  • 6,940
  • 5
  • 45
  • 89
  • This is not correct. The original data has the values 50...99. The error happens when 50 more values are added to the data model but only one row is added to the table view. – rmaddy Apr 30 '18 at 14:10
  • I am referring to row nums, not the values inside names array. – Nirav Bhatt Apr 30 '18 at 14:33
  • Right but the issue is adding only one row to the table view when 50 have been added to the data model. – rmaddy Apr 30 '18 at 14:35
  • @rmaddy yes, and my answer seems to point out the erroneous indexpath, isn't it? – Nirav Bhatt Apr 30 '18 at 14:38
  • But it's not wrong. There are now 100 values in the data model so an index path with a row of 99 is valid. Again, that's not the problem, Have a look at my answer. – rmaddy Apr 30 '18 at 14:40
0

1) Your model before ‘appendCells’ has 50 names count. 2) After call your mode is equal 100 names count but you only instert one cell at index path = 99? You need to insert 50 more rows instead of one.

Derp
  • 137
  • 1
  • 9
0

I was having this problem, and it worked with the following approach

 func insertRow(entries: [String]) {
        tableView.performBatchUpdates({
            self.tableView.insertRows(at: [IndexPath(row: entries.count - 1, section: 0)], with: .bottom)
        }, completion: nil)
    }