如何在视图出现之前滚动到iPhone上的UITableView的底部
我有一个UITableView填充可变高度的单元格。 当视图被推入视图时,我希望表格滚动到底部。 
我目前有以下function
 NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[log count]-1 inSection:0]; [self.table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; 
日志是一个可变数组,其中包含组成每个单元格内容的对象。
 上面的代码在viewDidAppear中工作正常,但是当视图第一次出现然后跳到底部时,这具有显示表顶部的viewDidAppear副作用。 如果table view可以滚动到底部之前,我会更喜欢它。 
 我在viewWillAppear和viewDidLoad尝试了滚动,但是在这两种情况下,数据还没有被加载到表中,并且都抛出exception。 
任何指导都会非常感激,即使只是告诉我我所拥有的一切都是可能的。
 我相信调用[table setContentOffset:CGPointMake(0, CGFLOAT_MAX)]将做你想要的。 
从雅各布的答案 ,这是代码:
 - (void) viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if (self.messagesTableView.contentSize.height > self.messagesTableView.frame.size.height) { CGPoint offset = CGPointMake(0, self.messagesTableView.contentSize.height - self.messagesTableView.frame.size.height); [self.messagesTableView setContentOffset:offset animated:YES]; } } 
我觉得最简单的方法是这样的:
 if (self.messages.count > 0) { [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.messages.count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } 
Swift 3版本:
 if messages.count > 0 { userDefinedOptionsTableView.scrollToRow(at: IndexPath(item:messages.count-1, section: 0), at: .bottom, animated: true) } 
如果您需要滚动到内容的EXACT末尾,可以这样做:
 - (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]; } 
我使用自动布局,没有答案为我工作。 这是我的解决scheme,终于奏效了:
 @property (nonatomic, assign) BOOL shouldScrollToLastRow; - (void)viewDidLoad { [super viewDidLoad]; _shouldScrollToLastRow = YES; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; // Scroll table view to the last row if (_shouldScrollToLastRow) { _shouldScrollToLastRow = NO; [self.tableView setContentOffset:CGPointMake(0, CGFLOAT_MAX)]; } } 
@JacobRelkin接受的解决scheme在iOS 7.0中不适用于我使用自动布局。
 我有一个UIViewController的自定义子类,并添加一个实例variables_tableView作为其view的子view 。 我使用自动布局来定位_tableView 。 我试图在viewDidLoad结尾调用这个方法,甚至在viewWillAppear: 。 都没有工作。 
 所以,我将下面的方法添加到我的UIViewController自定义子类。 
 - (void)tableViewScrollToBottomAnimated:(BOOL)animated { NSInteger numberOfRows = [_tableView numberOfRowsInSection:0]; if (numberOfRows) { [_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:numberOfRows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:animated]; } } 
 在viewDidLoad的末尾调用[self tableViewScrollToBottomAnimated:NO] 。 不幸的是,它也会导致tableView:heightForRowAtIndexPath:为每个单元tableView:heightForRowAtIndexPath:三次。 
 这是我在Swift 2.0中实现的一个扩展。 这些函数应该在tableview被加载后调用: 
 import UIKit extension UITableView { func setOffsetToBottom(animated: Bool) { self.setContentOffset(CGPointMake(0, self.contentSize.height - self.frame.size.height), animated: true) } func scrollToLastRow(animated: Bool) { if self.numberOfRowsInSection(0) > 0 { self.scrollToRowAtIndexPath(NSIndexPath(forRow: self.numberOfRowsInSection(0) - 1, inSection: 0), atScrollPosition: .Bottom, animated: animated) } } } 
其实一个“快捷”的方法是迅速做到这一点:
 var lastIndex = NSIndexPath(forRow: self.messages.count - 1, inSection: 0) self.messageTableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Bottom, animated: true) 
工作适合我。
细节
xCode 8.3.2,swift 3.1
码
 import UIKit extension UITableView { func scrollToBottom(animated: Bool) { let y = contentSize.height - frame.size.height setContentOffset(CGPoint(x: 0, y: (y<0) ? 0 : y), animated: animated) } } 
用法
 tableView.scrollToBottom(animated: true) 
我想要加载表格中显示的表格的末尾。 我发现使用
 NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:([self.tableView numberOfRowsInSection:0] - 1) inSection:0]; [[self tableView] scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; 
没有工作,因为当表格高度小于框架高度时出现错误。 注意我的表只有一个部分。
为我工作的解决scheme是在viewWillAppear中实现以下代码:
 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // on the initial cell load scroll to the last row (ie the latest Note) if (initialLoad==TRUE) { initialLoad=FALSE; NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:([self.tableView numberOfRowsInSection:0] - 1) inSection:0]; [[self tableView] scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; CGPoint offset = CGPointMake(0, (1000000.0)); [self.tableView setContentOffset:offset animated:NO]; } } 
BOOL ivar initialLoad在viewDidLoad中设置为TRUE。
对于Swift:
 if tableView.contentSize.height > tableView.frame.size.height { let offset = CGPoint(x: 0, y: tableView.contentSize.height - tableView.frame.size.height) tableView.setContentOffset(offset, animated: false) } 
 您应该使用UITableViewScrollPositionBottom来代替。 
 当然是一个Bug。 可能在代码中的某处使用table.estimatedRowHeight = value (例如100)。  将此值replace为您认为行高可以达到的最高值 ,例如500 ..这应该结合以下代码解决问题: 
 //auto scroll down example let delay = 0.1 * Double(NSEC_PER_SEC) let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) dispatch_after(time, dispatch_get_main_queue(), { self.table.scrollToRowAtIndexPath(NSIndexPath(forRow: self.Messages.count - 1, inSection: 0), atScrollPosition: UITableViewScrollPosition.Bottom, animated: false) }) 
对于Swift 3(Xcode 8.1):
 override func viewDidAppear(_ animated: Bool) { let numberOfSections = self.tableView.numberOfSections let numberOfRows = self.tableView.numberOfRows(inSection: numberOfSections-1) let indexPath = IndexPath(row: numberOfRows-1 , section: numberOfSections-1) self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.middle, animated: true) } 
使用上面的解决scheme,这将滚动到您的表的底部(只有在第一次加载表内容):
 //Scroll to bottom of table CGSize tableSize = myTableView.contentSize; [myTableView setContentOffset:CGPointMake(0, tableSize.height)]; 
经过很多的摆弄这是什么对我有用:
 var viewHasAppeared = false override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if !viewHasAppeared { goToBottom() } } override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) viewHasAppeared = true } private func goToBottom() { guard data.count > 0 else { return } let indexPath = NSIndexPath(forRow: data.count - 1, inSection: 0) tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: false) tableView.layoutIfNeeded() } 
 关键的结果是没有包装scrollToRowAtIndexPath里面的dispatch_async像一些build议,但只是跟随它调用layoutIfNeeded 。 
我的理解是,在当前线程中调用scroll方法可以保证在显示视图之前立即设置滚动偏移量。 当我调度到主线程时,视图在滚动生效前瞬间显示出来。
  (还要注意,你需要viewHasAppeared标志,因为每次调用viewDidLayoutSubviews你都不想goToBottom ,例如只要方向改变就会调用它。) 
在Swift 3.0中
 self.tableViewFeeds.setContentOffset(CGPoint(x: 0, y: CGFLOAT_MAX), animated: true) 
感谢雅各的答案。 真正有用的,如果有人用monodouch c#版本有趣
 private void SetScrollPositionDown() { if (tblShoppingListItem.ContentSize.Height > tblShoppingListItem.Frame.Size.Height) { PointF offset = new PointF(0, tblShoppingListItem.ContentSize.Height - tblShoppingListItem.Frame.Size.Height); tblShoppingListItem.SetContentOffset(offset,true ); } } 
使用这个简单的代码来滚动tableView底部
 NSInteger rows = [tableName numberOfRowsInSection:0]; if(rows > 0) { [tableName scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:rows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } 
如果您在向下滚动之前必须asynchronous加载数据,则可以使用以下解决scheme:
 tableView.alpha = 0 // We want animation! lastMessageShown = false // This is ivar viewModel.fetch { [unowned self] result in self.tableView.reloadData() if !self.lastMessageShown { dispatch_async(dispatch_get_main_queue()) { [unowned self] in if self.rowCount > 0 { self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: self.rowCount, inSection: 0), atScrollPosition: .Bottom, animated: false) } UIView.animateWithDuration(0.1) { self.tableView.alpha = 1 self.lastMessageShown = true // Do it once } } } } 
在swift 3上的function滚动到底部
  override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(false) //scroll down if lists.count > 2 { let numberOfSections = self.tableView.numberOfSections let numberOfRows = self.tableView.numberOfRows(inSection: numberOfSections-1) let indexPath = IndexPath(row: numberOfRows-1 , section: numberOfSections-1) self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.middle, animated: true) } } 
在iOS中,这对我来说工作得很好
 CGFloat height = self.inputTableView.contentSize.height; if (height > CGRectGetHeight(self.inputTableView.frame)) { height -= (CGRectGetHeight(self.inputTableView.frame) - CGRectGetHeight(self.navigationController.navigationBar.frame)); } else { height = 0; } [self.inputTableView setContentOffset:CGPointMake(0, height) animated:animated]; 
 它需要从viewDidLayoutSubviews调用 
[self.tableViewInfo scrollRectToVisible:CGRectMake(0,self.tableViewInfo.contentSize.height-self.tableViewInfo.height,self.tableViewInfo.width,self.tableViewInfo.height)animated:YES];
接受的答案不适用于我的表(数千行,dynamic加载),但下面的代码工作:
 - (void)scrollToBottom:(id)sender { if ([self.sections count] > 0) { NSInteger idx = [self.sections count] - 1; CGRect sectionRect = [self.tableView rectForSection:idx]; sectionRect.size.height = self.tableView.frame.size.height; [self.tableView scrollRectToVisible:sectionRect animated:NO]; } } 
不需要任何滚动,你可以通过使用这个代码来做到这一点:
 [YOURTABLEVIEWNAME setContentOffset:CGPointMake(0, CGFLOAT_MAX)]; 
如果以编程方式为tableview设置框架,请确保正确设置框架。
 func scrollToBottom() { let sections = self.chatTableView.numberOfSections if sections > 0 { let rows = self.chatTableView.numberOfRows(inSection: sections - 1) let last = IndexPath(row: rows - 1, section: sections - 1) DispatchQueue.main.async { self.chatTableView.scrollToRow(at: last, at: .bottom, animated: false) } } } 
你应该添加
 DispatchQueue.main.async { self.chatTableView.scrollToRow(at: last, at: .bottom, animated: false) } 
或者它不会滚动到底部。
在Swift中,你只需要
 self.tableView.scrollToNearestSelectedRowAtScrollPosition(UITableViewScrollPosition.Bottom, animated: true) 
使其自动滚动到button
在swift 3.0中如果你想要去tableview的任何特定单元格更改单元格索引值就像改变“self.yourArr.count”的值。
 self.yourTable.reloadData() self.scrollToBottom() func scrollToBottom(){ DispatchQueue.global(qos: .background).async { let indexPath = IndexPath(row: self.yourArr.count-1, section: 0) self.tblComment.scrollToRow(at: indexPath, at: .bottom, animated: true) } } 
我相信旧的解决scheme不适用于swift3。
如果您知道表格中的数字行,您可以使用:
 tableView.scrollToRow( at: IndexPath(item: listCountInSection-1, section: sectionCount - 1 ), at: .top, animated: true)