I am trying to scroll to the bottom of a UITableView after it is done performing [self.tableView reloadData]
I originally had
[self.tableView reloadData]
NSIndexPath* indexPath = [NSIndexPath indexPathForRow: ([self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1) inSection: ([self.tableView numberOfSections]-1)];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
But then I read that reloadData is asynchronous, so the scrolling doesn't happen since the self.tableView
, [self.tableView numberOfSections]
and [self.tableView numberOfRowsinSection
are all 0.
Thanks!
What's weird is that I am using:
[self.tableView reloadData];
NSLog(@"Number of Sections %d", [self.tableView numberOfSections]);
NSLog(@"Number of Rows %d", [self.tableView numberOfRowsInSection:([self.tableView numberOfSections]-1)]-1);
In the console it returns Sections = 1, Row = -1;
When I do the exact same NSLogs in cellForRowAtIndexPath
I get Sections = 1 and Row = 8; (8 is right)
Try this way it will work
I will execute when table is completely loaded
Other Solution is you can subclass UITableView
In Swift 3.0 + we can create a an extension for
UITableView
with aescaped Closure
like below :And Use it like Below where ever you want :
hope this will help to someone. cheers!
The
dispatch_async(dispatch_get_main_queue())
method above is not guaranteed to work. I'm seeing non-deterministic behavior with it, in which sometimes the system has completed the layoutSubviews and the cell rendering before the completion block, and sometimes after.Here's a solution that works 100% for me, on iOS 10. It requires the ability to instantiate the UITableView or UICollectionView as a custom subclass. Here's the UICollectionView solution, but it's exactly the same for UITableView:
CustomCollectionView.h:
CustomCollectionView.m:
Example usage:
See here for a Swift version of this answer
It appears folks are still reading this question and the answers. B/c of that, I'm editing my answer to remove the word Synchronous which is really irrelevant to this.
When [tableView reloadData]
returns, the internal data structures behind the tableView have been updated. Therefore, when the method completes you can safely scroll to the bottom. I verified this in my own app. The widely accepted answer by @rob-mayoff, while also confusing in terminology, acknowledges the same in his last update.If your
tableView
isn't scrolling to the bottom you may have an issue in other code you haven't posted. Perhaps you are changing data after scrolling is complete and you're not reloading and/or scrolling to the bottom then?Add some logging as follows to verify that the table data is correct after
reloadData
. I have the following code in a sample app and it works perfectly.As of Xcode 8.2.1, iOS 10, and swift 3,
You can determine the end of
tableView.reloadData()
easily by using a CATransaction block:The above also works for determining the end of UICollectionView's reloadData() and UIPickerView's reloadAllComponents().
Try setting delays: