Best way to check if UITableViewCell is completely visible
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A UITableViewCell can be visible, partially visible, or completely visible. If you only check whether the cell's index path appears in indexPathsForVisibleRows, you learn that some portion of it is on screen, but not whether the entire cell is inside the visible bounds. To check complete visibility, compare the cell's frame with the table view's visible rectangle.
Partial Visibility Is Not Enough
This common check answers only whether the row is at least partly visible:
That is useful sometimes, but it does not tell you whether the full cell is inside the table view viewport.
Check the Cell Frame Against the Visible Bounds
A practical full-visibility check looks like this:
rectForRow(at:) gives the row rectangle in the table view's own coordinate system, which makes it a good fit for comparing against tableView.bounds.
If the bounds fully contain the row rectangle, the cell is completely visible.
Why This Works Better Than Asking for the Cell
You might be tempted to fetch the cell and inspect its frame.
That works only if the cell already exists as a visible cell object. If the row is off-screen, cellForRow(at:) returns nil.
Using rectForRow(at:) is often cleaner because it works from layout information rather than requiring a live cell instance.
Account for Content Insets If Needed
In some layouts, safe-area handling or custom content insets affect what you consider "fully visible." If you need the visible content area rather than raw bounds, compute that rectangle explicitly.
Then compare the row rect against that adjusted visible area.
Useful in Scroll-Driven UI Logic
Complete visibility checks are handy for:
- autoplay or pause behavior
- starting an animation only when the whole cell is on screen
- analytics for fully viewed content
- deciding when to trigger more expensive work
The key is using the stricter definition when partial visibility would give the wrong behavior.
Common Pitfalls
The biggest mistake is relying on indexPathsForVisibleRows when the requirement is full visibility rather than partial visibility.
Another mistake is using cellForRow(at:) as if it were a visibility oracle for every row, even though it returns nil for off-screen cells.
A third issue is forgetting about content insets or safe-area adjustments when defining what counts as truly visible in the UI.
Summary
- '
indexPathsForVisibleRowstells you whether a row is at least partly visible, not fully visible' - For complete visibility, compare
rectForRow(at:)with the table view's visible bounds - '
rectForRow(at:)is often a better basis than requiring a live cell instance' - Adjust for content insets if your UI definition of visibility depends on them
- Use the stricter check only when full visibility actually matters for the feature

