viewDidLoad调用tableView.reloadData后,cellForRowAt为何触发不可见行?
cellForRowAt for Off-Screen Rows on Initial Load? Great question! This behavior isn't a bug—it's actually UITableView's built-in preloading mechanism designed to make scrolling smooth for users. Let me break down the details:
1. Preloading is intentional for smooth scrolling
Apple's UITableView doesn't just load cells that are strictly visible on the screen. It proactively loads cells that are just outside the visible bounds (above and below) so that when the user starts scrolling, those cells are already ready to display. This eliminates the lag that would happen if the app had to create/configure a cell on-the-fly mid-scroll.
When your cells are nearly as tall as the screen, this preloading becomes much more noticeable. Even though those extra cells aren't visible initially, they're within the system's "preload buffer"—so cellForRowAt gets called for them too.
2. How to confirm this is preloading
You can easily verify this by adding some debug code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellID", for: indexPath) as! YourCellType // Debug: Print cell position vs visible bounds let cellFrame = tableView.rectForRow(at: indexPath) let visibleBounds = tableView.bounds print("Cell \(indexPath.row) frame: \(cellFrame), Visible bounds: \(visibleBounds)") // Configure cell... return cell }
You'll see that the "off-screen" cells being loaded are just slightly outside the visible bounds—right where the user might scroll to next.
3. Can you control or disable this?
There's no public API to directly turn off or adjust the preload range, but you can tweak things to make it more predictable:
- Use accurate estimated row heights: If you're using auto-layout with
estimatedRowHeight, make sure the estimated value is as close as possible to the actual cell height. This helps the tableView calculate its preload buffer more accurately. - Optimize cell configuration: If preloading is causing performance issues (e.g., heavy image loading or data processing), move that work to background threads, cache results, or lazy-load content only when the cell is about to become visible (you can use
tableView(_:willDisplay:forRowAt:)for this).
Final note
This preloading behavior is normal and part of UITableView's core design to prioritize user experience. Instead of fighting it, focus on optimizing your cell setup logic to handle the preloaded cells efficiently.
内容的提问来源于stack exchange,提问作者Kesong Xie

