0

I'm having some troubles adding new cells on table view.

The strange thing is that I run once the function works perfectly without problems, if I do it for a second time it crash with this error.

* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSSingleObjectArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'

Here my code:

override func viewWillAppear(_ animated: Bool) {
    if prodottoDaAggiungere != nil {
        prodotti.append(prodottoDaAggiungere!)
        let indexPath = IndexPath(row: prodotti.count-1, section: 1)
        tableView.insertRows(at: [indexPath], with: .fade) // ?
        prodottoDaAggiungere = nil
    }
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if indexPath.row < prodotti.count && indexPath.section == 1 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ProdottoTableViewCell", for: indexPath) as! ProdottoTableViewCell // Crash :|
        let indexRow = indexPath.row // Fix
        cell.title.text = "\(prodotti[indexRow].prodotto.nome!) - \(prodotti[indexRow].prodotto.marca!)"
        cell.subtitle.text = "\(prodotti[indexRow].prodotto.formati[prodotti[indexRow].formato].dimensione) \(prodotti[indexRow].prodotto.unitàMisura!) - \(prodotti[indexRow].prodotto.formati[prodotti[indexRow].formato].prezzo) €"
        cell.number.text = Int(cell.stepper.value).description // 1
        cell.stepper.addTarget(self, action: #selector(stepperChanged), for: .valueChanged)
        return cell
    }

    return super.tableView(tableView, cellForRowAt: indexPath)
}

Using breakpoint I founded app crash on the dequeueReusableCell but I cannot understand why, someone could tell me why this code crash?

Here my tableView numberOfRowsInSection func:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    if section == 0 {
        return 1
    } else if section == 1 {
        return 1+prodotti.count
    } else {
        return 0
    }
}

Storyboard

Cell

Result

Really thanks AP

Andrea P.
  • 55
  • 8
  • can you share the prodotti array initialization? – Harish Feb 13 '20 at 19:43
  • try set indexPath row to `prodotti.count -1` – Mac3n Feb 13 '20 at 19:44
  • @Mac3n It crash again with the same error but now I can use use the function 2 times, crash the third. – Andrea P. Feb 13 '20 at 20:00
  • Could you please post the numberOfRowsInSection function ? – πter Feb 13 '20 at 20:02
  • @HarishSaran db.collection("Prodotti").whereField("Categoria", isEqualTo: category) .getDocuments() { (querySnapshot, err) in if let err = err { print("Error getting documents: \(err)") } else { for document in querySnapshot!.documents { self.prodotti.append(Prodotto(id: document.documentID, data: document.data())) } } } – Andrea P. Feb 13 '20 at 20:04
  • @πter added in question :) – Andrea P. Feb 13 '20 at 20:07
  • 2
    Never, never ever call `dequeueReusableCell` outside of `cellForRowAt`. It's completely pointless – the cell is created and thrown away at the end of the method – as well as `beginUpdates/endUpdates`. – vadian Feb 13 '20 at 22:57

3 Answers3

1

The issue is with this part:

let indexPath = IndexPath(row: prodotti.count, section: 1)

If prodotti.count is 2 then you are trying to scroll to the row with index 2, when the count is 2. You need to switch it so that you are going to count - 1, like this:

let indexPath = IndexPath(row: prodotti.count - 1, section: 1)

Additionally, you will need to update the array prodotti with new item you added. Since your number of rows in that section is prodotti + 2, it is working the first two times, but since you haven't actually increased the size of prodotti, the tableview doesn't know that there should now be more rows.

Wyetro
  • 8,439
  • 9
  • 46
  • 64
  • Hi, thanks a lot for the answer, I tried to modify the question by simplifying it but adding important data, maybe I can make you understand better. – Andrea P. Feb 13 '20 at 21:11
1

Arrays have bounds from index 0 to N - 1, being N = yourArray.count. So your upper bound should get to yourArray.count - 1. In your case:

let indexPath = IndexPath(row: prodotti.count - 1, section: 0)

Note that the sections also start with 0.

In other words: The number of elements is different from their actual indexes, which are their current position minus 1.

Alejandro Iván
  • 3,969
  • 1
  • 21
  • 30
0

I've got the solution for you:

https://stackoverflow.com/a/49157374/8737121

Really thanks to: Shan Ye

Andrea P.
  • 55
  • 8