Trung Hoang
Trung Hoang

Reputation: 94

dequeueReusableCell (withIdentifier identifier: String, for indexPath: IndexPath) returning 2 different cells at each call

don't know if you have encountered this situation, I use the function

func tableView(_ tableView: UITableView, 
     cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
  let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ReusableCell.self), for: indexPath) as! ReusableCell 
  cell.reloadAction = { 
    tableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .none) 
  } 
  return cell 
}

to retrieve reusable cell. But now every time I reload the cell, call this function again and it is returning 2 different cells at each call. I draw cells on the storyboard so I don't have the ability to register cells multiple times in the code. If you've ever encountered this case, please help me, I'm very confused :( Thank you very much.

Upvotes: 0

Views: 455

Answers (2)

Helge Becker
Helge Becker

Reputation: 3243

The dequeueReusableCell function is not returning the same cell instance for a given indexPath. It returns a previously allocated cell instance that is currently not used for memory efficiency or a new one if there is none available.

When a reload for a cell is triggered it will not reload the same instance, but jumps into the same cellForRowAt function that will return a reused or new cell.

You could cache all cells yourself and lookup them before requesting new ones. Not memory efficient, but you will have always the same cell instance for an IndexPath. There are corner cases where an own cache make sense. With many, many entries in the data model (lets say a list with 10000 songs) is the recycling of unused (aka not displayed) cells the best way.

How to update the cell then? Best practise to reload cells within a UITableView depends on the source of the event that requires the reload. The two events are either UI (User) related or data model related.

UI/User: You want a reload behaviour from within your cell? Then lets the cell query the data model and update its content. The cell could get its IndexPath as property along with a weak reference to the data model and asking the data model for the newest data. Or you ask the UITableViewDataSource what IndexPath belongs to the cell, to figure out what data relates to it.

Data Model: Why compute updates where are none? A more common and Apple-like way would be an update when the data changed. In this case would the data model know it was changed and trigger an update. Mostly is a reloadData() used, but you could also update all visible cells in a separate thread. For each cell you could use the UITableViewDataSource to tell you what IndexPath it has and decide then if that cell needs to update. Or each cell knows its IndexPath and decides on an update itself it this data is for this cell.

You may notice, there are many ways to update a cell. I don't know what approach suits the needs of your app best, but I think you have now some inspiration how to solve it. Cheers

Upvotes: 0

Charly Japan
Charly Japan

Reputation: 73

your identifier name seems strange (you don't need to specify its type (String): is that the one you have set in the interface builder pane? I suggest you to check the identifier name and give a try with a code like: withIdentifier: "myCell". Hope this will help.

Upvotes: 0

Related Questions