Cómo mantener UITableView contentoffset después de llamar -reloadData

CGPoint offset = [_table contentOffset]; [_table reloadData]; [_table setContentOffset:offset animated:NO]; //unuseful // __block UITableView *tableBlock = _table; // [self performBlock:^(id sender) { // [tableBlock setContentOffset:offset]; // } afterDelay:2]; 

No conozco ningún método de delegado que se reloadData después de reloadData . Y después de afterDelay:2 puede ser demasiado corto o demasiado largo, ¿cómo puedo implementarlo?

Mi inglés no es bueno, espero que puedas entender …

Recientemente estuve trabajando con reloadDatareloadData no cambia el contentOffset ni desplaza la vista de la tabla. De hecho, se mantiene igual si el desplazamiento es menor que la nueva cantidad de datos.

Estaba teniendo problemas con esto porque me meto con el tamaño de celda en mi método cellForRowAtIndexPath. Noté que la información de tamaño estaba desactivada después de hacer reloadData, así que me di count de que tenía que forzarla a la disposition inmediatamente antes de volver a configurar el desplazamiento de contenido.

 CGPoint offset = tableView.contentOffset; [tableView.messageTable reloadData]; [tableView layoutIfNeeded]; // Force layout so things are updated before resetting the contentOffset. [tableView setContentOffset:offset]; 

Llamar a reloadData en la tablaView no cambia la compensación de contenido. Sin embargo, si está utilizando UITableViewAutomaticDimension que se introdujo en iOS 8, podría tener un problema.

Al usar UITableViewAutomaticDimension , uno debe escribir el método de delegado tableView: estimatedHeightForRowAtIndexPath: y devolver UITableViewAutomaticDimension junto con tableView: heightForRowAtIndexPath: que también devuelve el mismo.

Para mí, tuve problemas en iOS 8 mientras usaba esto. Fue porque el método estimatedHeightForRowAtIndexPath: método estaba devolviendo valores inexactos aunque estaba usando UITableViewAutomaticDimension . Fue un problema con iOS 8, ya que no había ningún problema con los dispositivos iOS 9.

Resolví este problema usando un dictionary para almacenar el valor de la altura de la celda y devolverlo. Esto es lo que hice.

 - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { NSNumber *key = @(indexPath.row); NSNumber *height = @(cell.frame.size.height); [self.cellHeightsDictionary setObject:height forKey:key]; } - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { NSNumber *key = @(indexPath.row); NSNumber *height = [self.cellHeightsDictionary objectForKey:key]; if (height) { return height.doubleValue; } return UITableViewAutomaticDimension; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return UITableViewAutomaticDimension; } 

La comprobación de si existe una altura es por primera vez carga de página.

De manera pnetworkingeterminada, reloadData mantiene el contenidoOffset. Sin embargo, podría actualizarse si tiene valores incorrectos estimatedRowHeight.

Esto funcionó para mí ( Swift 3 )

 self.table.reloadData() self.table.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: true) 

Tuve el mismo problema pero ninguna de las respuestas sugeridas aquí funcionó. Así es como lo resolví. Subclass UITableView y anulación del layoutSubviews Método de layoutSubviews esta forma:

 override func layoutSubviews() { let offset = contentOffset super.layoutSubviews() contentOffset = offset } 

@Meharoof Najeeb's mostró la mejor solución para el problema de la altura estimada de las células. Pero a veces las lelas problema en diferentes lugares.
A veces, el problema se ensucia en el contenidoInsets de la vista de tabla. Si realiza la recarga de datos mientras tableView no está visible en la pantalla, puede enfrentarse con una compensación incorrecta después de que aparezca la vista de tabla en la pantalla.
Ocurre porque UIViewController puede controlar las inserciones si su scrollView, luego el scrollView, está apareciendo para permitir el mentira de scrollView debajo de la barra de navigation transparente y la barra de estado.
Me he enfrentado a este comportamiento en iOS 9.1

Esto está funcionando al 100%

 change the tableView.reloadData() 

dentro

 tableView.reloadRows(at: tableView!.indexPathsForVisibleRows!, with: .none) 

Swift 3 variante de la respuesta de Skywalker:

 fileprivate var heightDictionary: [Int : CGFloat] = [:] func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { heightDictionary[indexPath.row] = cell.frame.size.height } func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { let height = heightDictionary[indexPath.row] return height ?? UITableViewAutomaticDimension } 

Porque funciona bien

 [tView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];