Table view - Index out of range in cellForRowAt

I call tableView.reloadData() inside of didSet{} of the items variable. I got a crash in the cellForRowAt function only once, never before, never after with no code changes.

override func tableView(_ tableView: UITableView, number ofRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return items.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    cell.tag = indexPath.row
    let item = items[indexPath.row] //Thread 1: Fatal error: Index out of range
    cell.textLabel?.text = item.title

Upvotes: 1

Views: 6030

Answers (5)

Faysal Ahmed
Faysal Ahmed

Reputation: 7669

The possible solution will be you need to handle to solve the crash.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if(indexPath.row > items.count-1){
        return UITableViewCell()
      } else {
  
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.tag = indexPath.row
        let item = items[indexPath.row] //Thread 1: Fatal error: Index out of range
        cell.textLabel?.text = item.title

        return cell
     }
}

Maybe this will help.

Upvotes: 10

devang bhatt
devang bhatt

Reputation: 470

override func tableView(_ tableView: UITableView, number ofRowsInSection section: Int) -> Int {
    guard let items.count > 0 else {return 0}
    return items.count
}

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

I think items array does not have any value so it does crash. So, try this above code.

Upvotes: 0

iOS Geek
iOS Geek

Reputation: 4855

Try using some thing like this

var fileNameArray = [Audio](){
        didSet{
            if fileNameArray.count > 0{
                recordingListTableView.reloadData()
            }
        }
    }

Is It required to do this ?

crash Is index out of range

Are you Re-Updating Array After this didSet Statement ? if Yes, Do not use this DidSet case here , use if Array is not going to be updated again ,

If you still want to use , Also make use of WillSet Case After didSet()

Upvotes: 0

Swati Gautam
Swati Gautam

Reputation: 191

This crash appears when your index is more than array's count.

This crash may appear when scrolling the table view and table view get's updated. You are trying to fetch the index more than array count.

You can check the condition of indexpath.row less than array count.

Upvotes: 0

ghostatron
ghostatron

Reputation: 2650

I can see it happening if the table is scrolling quickly and you update the data source: it could hit a race condition where it tries to call cellForRowAt one more time before it realizes you changed the data source. As a precaution, I'd suggest always adding a check that your index is less than the array's count. Maybe it's paranoid, but better than a crash.

e.g:

  1. Array has 100 items.
  2. Swipe hard sending you towards bottom of table.
  3. While scrolling, the array is updated to only have 10 items.
  4. Table scroll asks for cell at row 99 because it didn't get the message yet.
  5. Crash when you ask for item 99 in an array with only 10 items.

Upvotes: 1

Related Questions