UITableView, scroll down to reboot?

I have a UITableView with cells that are dynamically updated. Everything works fine when tableview.reload is tableview.reload (see below) to update the cells in the table. I would like the table to scroll down to display new entries.

 - (void)reloadTable:(NSNotification *)notification { NSLog(@"RELOAD TABLE ..."); [customTableView reloadData]; // Scroll to bottom of UITable here .... } 

I planned to use scrollToRowAtIndexPath:atScrollPosition:animated: but then noticed that I did not have access to indexPath .

Does anyone know how to do this, or a delegate callback that I could use?

+59
objective-c iphone cocoa-touch
Feb 25 '11 at 0:40
source share
12 answers

Using:

 NSIndexPath* ipath = [NSIndexPath indexPathForRow: cells_count-1 inSection: sections_count-1]; [tableView scrollToRowAtIndexPath: ipath atScrollPosition: UITableViewScrollPositionTop animated: YES]; 

Or you can specify the index of the section manually (if one section => index = 0).

+121
Feb 25 2018-11-11T00:
source share

Another solution is to flip the table vertically and flip each cell vertically:

Apply the transform to a UITableView when initializing:

 tableview.transform = CGAffineTransformMakeScale(1, -1); 

and in cellForRowAtIndexPath:

 cell.transform = CGAffineTransformMakeScale(1, -1); 

This way you don't need workarounds for scrolling, but you will need to think a bit about contentInsets / contentOffsets and header / footer interactions.

+38
Feb 10 '15 at 15:16
source share
 -(void)scrollToBottom{ [self.tableView scrollRectToVisible:CGRectMake(0, self.tableView.contentSize.height - self.tableView.bounds.size.height, self.tableView.bounds.size.width, self.tableView.bounds.size.height) animated:YES]; } 
+33
Aug 16 '13 at 0:55
source share
 //In swift var iPath = NSIndexPath(forRow: self.tableView.numberOfRowsInSection(0)-1, inSection: self.tableView.numberOfSections()-1) self.tableView.scrollToRowAtIndexPath(iPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: true) 
+9
Sep 23 '14 at 1:49
source share

This is another solution that works well in my case when the cell height is large.

 - (void)scrollToBottom { CGPoint bottomOffset = CGPointMake(0, _bubbleTable.contentSize.height - _bubbleTable.bounds.size.height); if ( bottomOffset.y > 0 ) { [_bubbleTable setContentOffset:bottomOffset animated:YES]; } } 
+5
Jun 29 '13 at 11:20
source share

Since this is something you might want to use very often, I suggest you create a class extension in a UITableView:

 extension UITableView { func scrollToBottom(animated: Bool = true) { let section = self.numberOfSections if section > 0 { let row = self.numberOfRowsInSection(section - 1) if row > 0 { self.scrollToRowAtIndexPath(NSIndexPath(forRow: row - 1, inSection: section - 1), atScrollPosition: .Bottom, animated: animated) } } } } 
+5
Jan 19 '16 at 13:42 on
source share

Swift 3

For anyone here trying to figure out how to solve this problem, the key is to call .layoutIfNeeded() after .reloadData() :

 tableView.reloadData() tableView.layoutIfNeeded() tableView.setContentOffset(CGPoint(x: 0, y: tableView.contentSize.height - tableView.frame.height), animated: false) 

I worked with several sections in a UITableView and it worked well.

+2
May 16 '18 at 17:36
source share
Expansion

it's better to do in a UIScrollView instead of a UITableView, so it works on scrollView, tableView, collectionView (vertical), UIWebView (internal scroll view), etc.

 public extension UIScrollView { public func scrollToBottom(animated animated: Bool) { let rect = CGRectMake(0, contentSize.height - bounds.size.height, bounds.size.width, bounds.size.height) scrollRectToVisible(rect, animated: animated) } } 
+1
Apr 19 '16 at 18:15
source share

Fot swift 5

 extension UITableView { func scrollToBottom(animated: Bool = true) { let section = self.numberOfSections if section > 0 { let row = self.numberOfRows(inSection: section - 1) if row > 0 { self.scrollToRow(at: IndexPath(row: row-1, section: section-1), at: .bottom, animated: animated) } } } } 
+1
Aug 30 '19 at 6:29
source share

This is the best way.

 - (void)scrollToBottom { CGFloat yOffset = 0; if (self.tableView.contentSize.height > self.tableView.bounds.size.height) { yOffset = self.tableView.contentSize.height - self.tableView.bounds.size.height; } [self.tableView setContentOffset:CGPointMake(0, yOffset) animated:NO]; } 
0
Mar 06 '17 at 13:52 on
source share

try this code, it can help you:

  self.tableView.reloadData() DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.1, execute: { let indexPath = IndexPath(row: self.dateSource.count-1, section: 0) self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.bottom, animated: true) }) 
0
May 10 '18 at 8:41
source share

Swift 5

  func scrollToBottom() { let section = self.tableView.numberOfSections let row = self.tableView.numberOfRows(inSection: self.tableView.numberOfSections - 1) - 1; guard (section > 0) && (row > 0) else{ // check bounds return } let indexPath = IndexPath(row: row-1, section: section-1) self.tableView.scrollToRow(at: indexPath, at: .top, animated: true) } 

I do not agree that we should use cells_count , sections_count , self.dateSource.count , etc. Instead, a delegate would be better.

0
Jun 29 '19 at 3:07
source share



All Articles