We are observing that for devices with iPadOS 26, table views within apps are unexpectedly auto scrolling. The issue can be reproduced as follows:
- The table view has enough cells to the point where not all cells can fit on the screen and the table view is scrollable
- User has scrolled to the bottom of the tableView and tableView.reloadData() is called.
- One of the following applies:
- The ViewController containing the tableView is embedded in a UINavigationController, and ViewController sets self.edgesForExtendedLayout = .bottom
- The ViewController containing the tableView is embedded in a UINavigationController, and UINavigationController sets navigationBar.isTranslucent = false
- The following constraints are applied to the tableView:
tableView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
After thorough testing, we've found that the bug is only present in iPads with iPadOS 26. It does not show for iPhone devices or for iPads on iPadOS 18. We are hoping that this can be fixed as it is causing poor user experience.
Full code needed to reproduce the issue:
Use this willConnectTo function in SceneDelegate:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
window = UIWindow(windowScene: windowScene)
let navigationControllerWithVC = UINavigationController(rootViewController: ViewController())
// ⚠️ CASE 1 - Comment out the .isTranslucent setter below, or set the value to true, and the scrolling issue will be gone, granted that the other issue-causing lines in ViewController.swift
// are also commented.
navigationControllerWithVC.navigationBar.isTranslucent = false
window?.rootViewController = navigationControllerWithVC // Replace this line with window?.rootViewController = ViewController() to get rid of UINavigationController
window?.makeKeyAndVisible()
}
Use this ViewController class that is referenced from the SceneDelegate willConnectTo function:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableView: UITableView!
var safeArea: UILayoutGuide!
var timer: Timer!
override func viewDidLoad() {
super.viewDidLoad()
// ⚠️ CASE 2 - Uncomment the line below when this view is inside a UINavigationController to cause the scrolling issue.
//self.edgesForExtendedLayout = .bottom
tableView = UITableView()
safeArea = view.layoutMarginsGuide
setupTableView()
timer = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(fireTimer), userInfo: nil, repeats: true)
}
@objc public func fireTimer() {
tableView.reloadData()
print("Reloaded table")
}
func setupTableView() {
tableView.delegate = self
tableView.dataSource = self
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
// ⚠️ CASE 3 - Replace view.topAnchor in the next line below with safeArea.topAnchor to see the scrolling issue, regardless if view is inside a UINavigationController.
tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
40
}
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
50.0
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = indexPath.row == 39 ? "END" : "Row \(indexPath.row)"
return cell
}
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
For reproducing this on iPadOS 26 simulators, I can confirm that simulators under Xcode 26.0.1 (17A400) and Xcode 26.1 Beta (17B5025f) will show the issue. The issue is present in iPadOS 26 and iPadOS 26.1 beta.
I've also submitted Apple Feedback for this (FB20357980) with all this code in a Xcode project.
In your code snippet you had:
navigationControllerWithVC.navigationBar.isTranslucent = false
We don't recommend using isTranslucent
for this level of customization in UINavigationBar
. For iOS 18 and below, use UINavigationBarAppearance
for customization purposes and starting in iOS 26, reduce your use of custom backgrounds in navigation elements and controls. Prefer to remove custom effects and let the system determine the navigation bar background appearance. Please review Customizing your app’s navigation bar and TN3106: Customizing the appearance of UINavigationBar
You also called:
tableView.reloadData()
We also don't recommend you calling reloadData
. Ideally use a combination of UITableViewDiffableDataSource which handles automatically diffing sections & items for you, and generating the correct batch updates on the tableView or your own change detection for properties within existing items so you can call the reconfigure or reload APIs on the diffable snapshot as needed, to update content within existing views.