Why we use dequeueReusableCellWithIdentifier

Wait, not those cells!

With the very first table view I implemented in iOS, I was using tableView.dequeueReusableCellWithIdentifier. If you’ve ever used a table view before, you probably know what this does.

In short, it gets the cell from your Storyboard and allows you to use it when calling tableView(... cellForRowAt indexPath: IndexPath)....

But why do we do this and how does it work?

I’ll preface the next section with a question. If my tableView had 10,000 rows and each cell had an image and lots of text, after scrolling down extremely far, wouldn’t the app crash from running out of memory?


Bad Table View

So to the question above, yes. Yes it would. But whenever I’m using a table view, this doesn’t happen. So what’s happening? First, we’ll explore why we don’t do it the way I’m about to show you — with 1,000 rather than 10,000 cells.

First we set up our variables.

// MARK: — Instance Vars
@IBOutlet weak var tableView: UITableView!
var cells: [BadTableViewCell] = []

Next we start with our view lifecycle. Here we’ll only need viewDidLoad()

// MARK: — View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
cellsSetup()
tableViewSetup()
}

And then we have our setup.

// MARK: — Setup
func tableViewSetup() {
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 350
}
func cellsSetup() {
for _ in 0…1000 {
let cell = Bundle.main.loadNibNamed(“BadTableViewCell”, owner: self, options: nil)?[0] as! BadTableViewCell
cells.append(cell)
}

Then we can easily display the cells based on the array we set up.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = cells[indexPath.row]
return cell
}

This should immediately throw a red flag. We’re adding all our cells to a cell array as soon as the view is loaded, using up a ton of memory compared to reusing a cell.

12.3 MB in memory

Better Table View

The solution to the issue above is what we’ve been using all along! dequeueReusableCellWithIdentifier. Instead of creating every single cell and then selectively displaying them, we only create a handful of cells, enough to fill the screen and a little more. As we scroll, we reuse the cells offscreen, leading to a much more memory efficient task.

Only 5.1 MB in memory

First thing we do is register our cell. If you are using a Storyboard and have a cell setup there with a reuse identifier, you don’t have to do this part.

tableView.register(UITableViewCell.self, forCellReuseIdentifier: “BetterTableViewCell”)

Next we use our friend the dequeueReusableCellWithIdentifier.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "BetterTableViewCell")
cell?.textLabel?.text = "Wow much better"
return cell!
}

So this implementation is awesome, and now all the cells are being reused as they should be.

Issues with images in reuse

However, If you have images loading in to your cell and you’re scrolling through fast and your internet connection isn’t the best, you’ll start noticing some images are where they shouldn’t be. This is because we are reusing cells, so the text and images are being rolled over, leading to the wrong images in the wrong cells.

Old version of Course Board

We fix this in our Best Table View implementation.


Best Table View

All we need to do to is use the prepareForReuse() function. This function is called before cell reuse, letting you cancel current requests and perform a ‘reset’.

Below I show you what a custom table view cell might look like.

Add the code below to the UITableViewCell and you should be good to go.

override func prepareForReuse() {
mainImageView.af_cancelImageRequest()
mainImageView.image = nil
}

Now your table view scrolling will be smooth (through cell reuse) and incorrect images will not carry over (through prepareForReuse()).

New version of Course Board (coming soon!)

Conclusions and Resources

I hope you enjoyed the short explanation of why we use dequeueReusableCellWithIdentifier in our code. You can check out some more info below with the link to Apple’s documentation.