'How to scroll UITableView to desired row even before visible to user?

I was wondering, is it possible to scroll the UITableView to desired row, even before it is visible to user, so that such scroll action is not aware to user?

Currently, here is my code to perform scrolling to desired row.

class ThemeTableViewController: UITableViewController {
    private var firstTime = true
 
    private func scrollRectToVisible() {
        let theme = WeNoteOptions.theme
        if let index = Theme.allCases.firstIndex(of: theme) {
            let indexPath = IndexPath(row: index, section: 0)
            let rect = tableView.rectForRow(at: indexPath)
            tableView.scrollRectToVisible(rect, animated: true)
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        if firstTime {
            firstTime.toggle()
            scrollRectToVisible()
        }
    }

Please note that, placing scrollRectToVisible in the following functions will not work. So far, viewDidAppear is the only place for scrollRectToVisible to work.

  • viewDidLoad - scrollRectToVisible doesn't work here.
  • viewWillAppear - scrollRectToVisible doesn't work here.

Here's is the outcome so far.

enter image description here

User will notice the auto scroll action.

We would like the scroll action not aware to user.

Is it possible that when UITableView is visible to user for the first time, the last row (green Avocado) is already visible?



Solution 1:[1]

Inside viewDidLayoutSubviews

if tableView.numberOfRows(inSection: 0) != 0 {
  scrollRectToVisible()   
}

with animated: false)

tableView.scrollRectToVisible(rect, animated: false)

Solution 2:[2]

I called tableView.scrollRectToVisible(rect, animated: false) with animated as false, from viewDidAppear method and the result were as expected.

I have copied and changed based on your code above. Here, I have added animated:bool as parameter in your method scrollRectToVisible to control animation part as needed.

class ThemeTableViewController: UITableViewController {
    private var firstTime = true

    // added new parameter `animated`
    private func scrollRectToVisible(_ animated: Bool = true) {
        let theme = WeNoteOptions.theme
        if let index = Theme.allCases.firstIndex(of: theme) {
            let indexPath = IndexPath(row: index, section: 0)
            let rect = tableView.rectForRow(at: indexPath)

            // replaced true with `animated`
            tableView.scrollRectToVisible(rect, animated: animated)
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        if firstTime {
            firstTime.toggle()
            // animation = false.
            scrollRectToVisible(false)
        }
    }
}

Solution 3:[3]

Here consider itemCount = last item of your array

Add code in viewDidload method after your array contains data.

tableView.reloadData()
let indexPath = IndexPath(item: itemCount, section: 0)
print("indexPath",indexPath)
tableView.scrollToRow(at: indexPath, at: .none, animated: false)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sh_Khan
Solution 2 Dharman
Solution 3 Navin Amulani