TableView slow when adding images to cellForRowAtIndex
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
UITableView scrolling becomes sluggish when cellForRowAt does too much work on the main thread. Image loading is a common cause because decoding, resizing, disk access, and network fetches are expensive compared with the lightweight view configuration that table view cells are supposed to do.
The fix is not to stop using images. The fix is to separate image retrieval from cell configuration and let reuse, caching, and asynchronous loading work together.
Why cellForRowAt Gets Slow
cellForRowAt is called repeatedly while the user scrolls. That means any slow work inside it is multiplied across many rows. Common causes include:
- downloading images synchronously
- decoding large image files on the main thread
- resizing full-resolution images for tiny thumbnails
- failing to reuse cached results
A slow version often looks like this:
Data(contentsOf:) blocks the current thread. If this runs on the main thread during scrolling, frame drops are almost guaranteed.
What Good Cell Configuration Looks Like
Cell configuration should be fast and deterministic:
- set labels
- set placeholder images
- kick off image loading if needed
- return immediately
A better pattern is to use asynchronous loading plus caching:
And then use it in the table view:
This keeps the table responsive because the cell is returned immediately.
Cell Reuse and Wrong Images
Because cells are reused, asynchronous loading introduces another issue: by the time the image arrives, the cell may represent a different row. One way to handle that is to move the image-loading logic into a custom cell and track the active URL.
Then check the URL before assigning the image:
That prevents flickering and mismatched thumbnails.
Resize Images for Display Size
Even if loading is asynchronous, using full-size photos as thumbnails wastes memory and CPU. If a cell shows a 60x60 image, storing and decoding a multi-megabyte photo for every row is expensive.
A better approach is to:
- fetch a smaller image from the server when possible
- preprocess thumbnails in the background
- cache the resized result, not only the original
Performance problems are often more about image size than about the table view itself.
Common Pitfalls
The biggest pitfall is doing synchronous work in cellForRowAt, especially network or disk-heavy image loading.
Another issue is ignoring cell reuse. Without reuse-aware checks, asynchronous callbacks can apply the wrong image to a recycled cell.
Large image decoding is also a hidden cost. Even cached images can hurt scrolling if they are much larger than the display size.
Finally, avoid reloading the whole table view every time a single image finishes. Update only the visible cell or the affected row to keep scrolling smooth.
Summary
- '
cellForRowAtshould configure cells quickly and return immediately.' - Load images asynchronously and cache the results.
- Use placeholders and reuse-aware checks to avoid wrong-image flicker.
- Resize or request smaller thumbnails instead of decoding full-size images for table cells.
- Most
UITableViewimage lag comes from main-thread work, not from the table view itself.

