UITableView
iOS Development
Swift Programming
Mobile App Development
Scroll Function

How to scroll to the exact end of the UITableView?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Scrolling a UITableView to the bottom sounds like a single API call, but there are two slightly different goals: scroll to the last row, or scroll to the absolute bottom of the content including insets and partially visible space. Which one you need depends on whether you are building something like a chat screen, a feed, or a table with dynamic row heights.

Scrolling to the Last Row

If you simply want the last cell visible, scrollToRow is the most direct approach:

swift
1func scrollToLastRow(tableView: UITableView, animated: Bool) {
2    let lastSection = tableView.numberOfSections - 1
3    guard lastSection >= 0 else { return }
4
5    let lastRow = tableView.numberOfRows(inSection: lastSection) - 1
6    guard lastRow >= 0 else { return }
7
8    let indexPath = IndexPath(row: lastRow, section: lastSection)
9    tableView.scrollToRow(at: indexPath, at: .bottom, animated: animated)
10}

This is usually the right answer when the table represents discrete rows and you want the final item aligned near the bottom.

Scrolling to the Exact Content End

If you need the exact bottom of the scrollable content, compute the content offset directly:

swift
1func scrollToExactBottom(tableView: UITableView, animated: Bool) {
2    tableView.layoutIfNeeded()
3
4    let bottomOffsetY =
5        tableView.contentSize.height
6        - tableView.bounds.height
7        + tableView.adjustedContentInset.bottom
8
9    let targetY = max(-tableView.adjustedContentInset.top, bottomOffsetY)
10    let targetPoint = CGPoint(x: 0, y: targetY)
11
12    tableView.setContentOffset(targetPoint, animated: animated)
13}

This gives more precise control because it uses the actual content height rather than the position of a specific row.

Why Timing Matters

A common reason bottom scrolling fails is that the table has not finished laying out its cells yet. If row heights are dynamic or you just called reloadData(), the final contentSize may not be correct at the moment you try to scroll.

That is why code often needs:

  • 'tableView.layoutIfNeeded()'
  • scrolling in viewDidLayoutSubviews
  • or dispatching the scroll after the reload cycle finishes

Without correct timing, the scroll can stop above the true bottom.

Chat-Style Use Case

For chat UIs, a common pattern is:

swift
1messages.append(newMessage)
2tableView.reloadData()
3DispatchQueue.main.async {
4    scrollToExactBottom(tableView: self.tableView, animated: true)
5}

The asynchronous dispatch gives the table a chance to finish the current UI update cycle before the scroll occurs.

Empty Tables and Edge Cases

Always guard against:

  • zero sections
  • zero rows
  • content shorter than the table's visible height

If the content is shorter than the viewport, the exact bottom offset would be negative without clamping. That is why the example uses max(...) to avoid scrolling past the top inset.

Sectioned Tables

If your table has multiple sections, "last row" means the final row in the final non-empty section, not simply the last row of section zero. That sounds obvious, but it is an easy bug in apps that group content by day, category, or message batch.

Common Pitfalls

The most common mistake is calling scrollToRow on an empty table. That produces an invalid index path and crashes.

Another issue is scrolling immediately after reloadData() without waiting for layout. The table may not yet know its final content size.

People also confuse "bottom row visible" with "exact content end." Those are close, but not always identical when there are content insets, dynamic heights, or partially visible rows.

Finally, if you have keyboard avoidance or safe-area adjustments, use adjustedContentInset rather than assuming zero insets.

Summary

  • Use scrollToRow when you want the last row visible.
  • Use contentSize and setContentOffset when you need the exact scrollable bottom.
  • Ensure layout is up to date before computing the scroll target.
  • Guard against empty data and short content.
  • Account for content insets, especially in chat-style interfaces and keyboard-driven screens.

Course illustration
Course illustration

All Rights Reserved.