I've been fighting on this one for over two weeks now: Scrolling after tableView.reloadData() does not work for me reliably. Here's what I'm doing (code follows).
1. I have an array of RSS objects fetched from the web, once fetched these object get loaded in `feedManager.arrayOfFeedItems`.
2. When it's time to refresh the feeds the app will:
a) MODEL: Copy `feedManager.arrayOfFeedItems` into `feedManager.previousArrayOfFeedItems`, this is done so when is time to reload the table I can know what article was being read by the user at the top of the app.
It will then fetch new articles and add them, if appropriate, to `feedManager.arrayOfFeedItems`. Once all articles have been fetched it will tell the TVC to reload the table.
b) TVC: It begins `tableView.beginUpdates()`, grabs the article we should go to and stores it into `articleToGoTo` by using `feedManager.previousArrayOfFeedItems[tableView.rows(in: tableView.visibleRect).lowerBound]` and then reloads the data using `tableView.reloadData()`. Using the stored article we will get its position in the updated array using: `let rowToGoTo = feedManager.arrayOfFeedItems.index(of: articleToGoTo!)!`. At that point we will scroll to that row by calling 'tableView.scrollRowToVisible(rowToGoTo)' and we will endUpdates `tableView.endUpdates()`.
EXPECTATION: The app reloads the data and goes to the right cell.
REALITY: Ignores me completely, IF I add a timer that then executes the `scrollCellToVisible(row: row)` like so `Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(test) , userInfo: nil, repeats: false)`, THEN it works.
What am I missing? Why can't I run it without a timer?
func updateTableView(){
tableView.beginUpdates()
var articleToGoTo : FeedItemComponents? = nil
if feedManager.previousArrayOfFeedItems.count > 0 {
articleToGoTo = feedManager.previousArrayOfFeedItems[tableView.rows(in: tableView.visibleRect).lowerBound]
}
tableView.reloadData()
if articleToGoTo != nil {
let rowToGoTo = feedManager.arrayOfFeedItems.index(of: articleToGoTo!)!
print("Scrolling to: \(articleToGoTo!.title), at index: \(rowToGoTo)")
scrollCellToVisible(row: rowToGoTo)
}
tableView.endUpdates()
print("UPDATE TABLE VIEW - DONE")
}
For reference, scrollCellToVisible is a function that scrolls to the top, I don't think there's an issue with it but posting it here just in case:
@objc func scrollCellToVisible(row: Int) {
let rowRect = tableView.rect(ofRow: row)
let scrollOrigin = rowRect.origin
let clipView = tableView.superview as? NSClipView
clipView!.animator().setBoundsOrigin(scrollOrigin)
Some extra info:
The number of cells and their height changes depending on the information fetched.
I'm using the newly introduced: Table View Row Size Stype: Automatic(Auto Layout).
Thanks a million in advance for any tips that help me solve this.