Cómo desplazarse hasta la parte inferior de una UITableView en el iPhone antes de que aparezca la vista

Tengo una UITableView que está poblada con celdas de altura variable. Me gustaría que la tabla se desplace hacia abajo cuando la vista se muestre a la vista.

Actualmente tengo la siguiente función

 NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[log count]-1 inSection:0]; [self.table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; 

log es una matriz mutable que contiene los objetos que componen el contenido de cada celda.

El código anterior funciona bien en viewDidAppear pero tiene el desafortunado efecto secundario de mostrar la parte superior de la tabla cuando aparece la vista por primera vez y luego saltar al fondo. Preferiría que la table view se desplazara hacia abajo antes de que aparezca.

Intenté el desplazamiento en viewWillAppear y viewDidLoad pero en ambos casos los datos no se han cargado aún en la tabla y ambos lanzan una excepción.

Cualquier orientación sería muy apreciada, incluso si solo es cuestión de decirme lo que tengo es todo lo que es posible.

Creo que llamando [table setContentOffset:CGPointMake(0, CGFLOAT_MAX)] hará lo que quiera.

De la respuesta de Jacob , este es el código:

 - (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]; } } 

Creo que la manera más fácil es esta:

 if (self.messages.count > 0) { [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.messages.count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } 

Versión de Swift 3:

 if messages.count > 0 { userDefinedOptionsTableView.scrollToRow(at: IndexPath(item:messages.count-1, section: 0), at: .bottom, animated: true) } 

Si necesita desplazarse al final EXACTO del contenido, puede hacerlo así:

 - (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]; } 

Estoy usando el diseño automático y ninguna de las respuestas funcionó para mí. Aquí está mi solución que finalmente funcionó:

 @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)]; } } 

La solución aceptada por @JacobRelkin no funcionó en iOS 7.0 utilizando Auto Layout.

Tengo una subclase personalizada de UIViewController y agregué una variable de instancia _tableView como subvista de su view . Posicione _tableView usando el diseño automático. Intenté llamar a este método al final de viewDidLoad e incluso en viewWillAppear: Ninguno funcionó.

Entonces, agregué el siguiente método a mi subclase personalizada de UIViewController .

 - (void)tableViewScrollToBottomAnimated:(BOOL)animated { NSInteger numberOfRows = [_tableView numberOfRowsInSection:0]; if (numberOfRows) { [_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:numberOfRows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:animated]; } } 

Llamar a [self tableViewScrollToBottomAnimated:NO] al final de viewDidLoad funciona. Desafortunadamente, también causa que tableView:heightForRowAtIndexPath: tres veces para cada celda.

Aquí hay una extensión que implementé en Swift 2.0. Estas funciones deben tableview se haya cargado la 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) } } } 

Detalles

xCode 8.3.2, swift 3.1

Código

 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) } } 

Uso

 tableView.scrollToBottom(animated: true) 

En realidad, una manera “rápida” de hacerlo rápido es:

 var lastIndex = NSIndexPath(forRow: self.messages.count - 1, inSection: 0) self.messageTableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Bottom, animated: true) 

trabajo perfecto para mi

Quería que la mesa se cargara con el extremo de la tabla que se muestra en el marco. He encontrado usando

 NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:([self.tableView numberOfRowsInSection:0] - 1) inSection:0]; [[self tableView] scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; 

no funcionó porque dio un error cuando la altura de la tabla era menor que la altura del cuadro. Tenga en cuenta que mi mesa solo tiene una sección.

La solución que funcionó para mí fue implementar el siguiente código en 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 se establece en TRUE en viewDidLoad.

Para 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) } 

Debería usar UITableViewScrollPositionBottom en UITableViewScrollPositionBottom lugar.

Para 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) } 

Es por supuesto un error. Probablemente en algún lugar de su código utilice table.estimatedRowHeight = value (por ejemplo, 100). Reemplace este valor por el valor más alto que crea que podría obtenerse una altura de fila , por ejemplo 500. Esto debería resolver el problema en combinación con el siguiente código:

 //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) }) 

Usando las soluciones anteriores, esto se desplazará al final de la tabla (solo si el contenido de la tabla se carga primero):

 //Scroll to bottom of table CGSize tableSize = myTableView.contentSize; [myTableView setContentOffset:CGPointMake(0, tableSize.height)]; 

Después de mucho toquetear esto es lo que funcionó para mí:

 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() } 

La clave resultó no estar ajustando scrollToRowAtIndexPath dentro de dispatch_async como algunos han sugerido, sino simplemente siguiéndolo con una llamada a layoutIfNeeded .

Mi comprensión de esto es que, al llamar al método de desplazamiento en el hilo actual, se garantiza que el desplazamiento de desplazamiento se establece inmediatamente, antes de que se muestre la vista. Cuando estaba enviando al hilo principal, la vista se mostraba por un instante antes de que el rollo tuviera efecto.

(También NB necesita el indicador viewHasAppeared porque no desea goToBottom a goToBottom cada vez que se viewDidLayoutSubviews . Se llama, por ejemplo, cada vez que cambia la orientación).

En Swift 3.0

 self.tableViewFeeds.setContentOffset(CGPoint(x: 0, y: CGFLOAT_MAX), animated: true) 

Gracias Jacob por la respuesta. realmente útil si alguien interesante con la versión de monotouch 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 ); } } 

Usa este código simple para desplazarte a TableView bottom

 NSInteger rows = [tableName numberOfRowsInSection:0]; if(rows > 0) { [tableName scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:rows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } 

Si tiene que cargar los datos de forma asincrónica antes de desplazarse hacia abajo, aquí está la posible solución:

 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 } } } } 

Función en swift 3 scroll to bottom

  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) } } 

En iOS, esto funcionó bien para mí

 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]; 

Necesita ser llamado desde viewDidLayoutSubviews

[self.tableViewInfo scrollRectToVisible: CGRectMake (0, self.tableViewInfo.contentSize.height-self.tableViewInfo.height, self.tableViewInfo.width, self.tableViewInfo.height) animado: SÍ];

La respuesta aceptada no funcionó con mi tabla (miles de filas, carga dinámica) pero el código siguiente funciona:

 - (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]; } } 

No es necesario desplazarse, puede hacerlo utilizando este código:

 [YOURTABLEVIEWNAME setContentOffset:CGPointMake(0, CGFLOAT_MAX)]; 

Si está configurando el marco para la tabla vista programáticamente, asegúrese de que está configurando el marco correctamente.

 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) } } } 

deberías agregar

 DispatchQueue.main.async { self.chatTableView.scrollToRow(at: last, at: .bottom, animated: false) } 

o no se desplazará hacia abajo.

En Swift, solo necesitas

 self.tableView.scrollToNearestSelectedRowAtScrollPosition(UITableViewScrollPosition.Bottom, animated: true) 

para que se desplace automáticamente al botón

En swift 3.0 Si desea ir a cualquier celda particular de la tabla vista Cambiar el índice de la celda Valor como cambiar el valor “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) } } 

Creo que las soluciones antiguas no funcionan con swift3.

Si conoce las filas numéricas de la tabla, puede usar:

 tableView.scrollToRow( at: IndexPath(item: listCountInSection-1, section: sectionCount - 1 ), at: .top, animated: true)