reloadData of UITableView with Dynamic cell heights causes jumpy scrolling
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Calling reloadData() on a UITableView with self-sizing cells (dynamic heights) frequently causes the scroll position to jump unpredictably. This happens because the table view discards all cached cell heights and re-estimates them, causing the content offset to shift. This is one of the most common UITableView performance issues in iOS development.
Why It Happens
When you call reloadData(), the table view:
- Discards all previously calculated cell heights
- Uses
estimatedRowHeightfor all cells that are not currently visible - Recalculates heights only for visible cells using Auto Layout
- Adjusts
contentSizeandcontentOffsetbased on the new estimates
If the estimated heights differ significantly from the actual heights, the content shifts, producing the "jump."
Solution 1: Cache Cell Heights (Best Fix)
Store the actual height of each cell after it is displayed, then return the cached value as the estimate:
This ensures that after the first display, estimated heights match actual heights exactly, eliminating jumps on reloadData().
Solution 2: Use Targeted Reloads Instead of reloadData()
Instead of reloading the entire table, update only the rows that changed:
Targeted reloads only recalculate heights for the affected rows, preserving the scroll position for everything else.
Solution 3: Save and Restore Content Offset
Manually preserve the scroll position across a reload:
This is a simple workaround but does not address the root cause and may produce a brief visual flicker.
Solution 4: Use UITableViewDiffableDataSource (iOS 13+)
Diffable data sources automatically compute the minimal set of changes and animate them without jumps:
This is the recommended approach for iOS 13+ as it eliminates the need for reloadData() in most cases.
Solution 5: Better Estimated Row Heights
If your cells have predictable height patterns, set a more accurate estimate:
Solution 6: Disable Estimated Heights Entirely
For small datasets, you can disable estimation entirely (not recommended for large lists):
This forces the table view to calculate all cell heights upfront. It eliminates jumping but causes a performance hit on large datasets because all cells must be measured before display.
Complete Working Example
Common Pitfalls
- Forgetting to invalidate the cache: When data changes (items reordered, deleted, or content updated), the cached heights become stale. Clear the cache for affected index paths before reloading.
- Setting estimatedRowHeight to 0 on large datasets: This forces the table view to measure every cell upfront, causing a noticeable delay before the table appears. Only use this for tables with fewer than ~50 rows.
- Auto Layout ambiguity: If your cell's constraints do not fully define the height, the table view falls back to an incorrect height. Verify constraints pin from top to bottom of the
contentView. - Section headers/footers: The same jumping issue affects section headers and footers. Cache their heights with
estimatedHeightForHeaderInSectionas well. - reloadData on background thread: Calling
reloadData()from a background thread causes undefined behavior including jumps. Always dispatch to the main queue.
Summary
| Approach | Effort | Effectiveness |
| Cache cell heights | Medium | Best — eliminates jumps |
| Targeted reloads | Low | Great — avoids full reload |
| DiffableDataSource | Medium | Great — modern approach |
| Better estimates | Low | Good — reduces jumps |
| Save/restore offset | Low | Workaround — may flicker |
| Disable estimation | Low | Works but slow for large lists |
Related reading
- Remove all occurrences of a value from a list?
- Remove all unused resources from an android project
- Remove all whitespace in a string
- Remove data from tensorboard event files to make them smaller
- reloadData of UITableView with Dynamic cell heights causes jumpy scrolling
- Remove all constraints affecting a UIView
- Remove duplicate objects from an array using javascript
- Remove elements from collection while iterating

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.