Hacer UITableView mantener la position de desplazamiento al agregar celdas en la parte superior

Ok, entonces lo que necesito es evitar el desplazamiento de la vista de tabla cuando se agreguen nuevos elementos por encima de la fila visible actual. Estoy usando NSFetchedResultsController con muchos objects (como 10 000) y reloadData funciona bastante bien cuando no estoy tocando contentOffset.

Sin embargo, cuando trato de manipular ContentOffset para mantener la position de desplazamiento cuando se insertan nuevas inputs, comienza a congelar la interfaz de usuario por unos 300 ms, lo que es malo para mí.

¿Alguien puede sugerir una solución mejor (más rápida) de cómo mantener la vista de tabla en la misma celda cuando se agregan nuevos elementos en la parte superior?

Y este es el código que estoy usando actualmente para rastrear inserciones y cambiar contentOffset. No admite animaciones y diferentes tamaños de celdas.

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { switch(type) { case NSFetchedResultsChangeInsert: [_insertions addObject:@(newIndexPath.row)]; break; } } - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { _insertions = @[].mutableCopy; } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { NSMutableArray *copy = _insertions.mutableCopy; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSSortDescriptor *lowestToHighest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES]; [copy sortUsingDescriptors:[NSArray arrayWithObject:lowestToHighest]]; dispatch_sync(dispatch_get_main_queue(), ^{ for (NSNumber *i in copy) { [self p_delayedAddRowAtIndex:[i integerValue]]; } [self.tableView reloadData]; }); }); } - (CGFloat)p_firstRowHeight { return [self tableView:[self tableView] heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; } -(void)p_delayedAddRowAtIndex:(NSInteger)row { NSIndexPath *firstVisibleIndexPath = [[self.tableView indexPathsForVisibleRows] firstObject]; if (firstVisibleIndexPath.row >= row) { CGPoint offset = [[self tableView] contentOffset]; offset.y += [self firstRowHeight]; if ([self.tableView visibleCells].count > self.tableView.frame.size.height / [self firstRowHeight]) { [[self tableView] setContentOffset:offset]; } } } 

Ok, después de algunas respuestas que me indicaron en la dirección correcta, se me ocurrió esta solución. Funciona sin problemas, sin embargo, algunas coorderadas feos de matemáticas y no admite diferentes tamaños de celdas. Espero que sea útil para alguien.

 -(void)controllerWillChangeContent:(NSFetchedResultsController *)controller { NSIndexPath *firstVisible = [[self.tableView indexPathsForVisibleRows] firstObject]; self.topVisibleMessage = [self.fetchedResultsController objectAtIndexPath:firstVisible]; NSIndexPath *topIndexPath = [self.fetchedResultsController indexPathForObject:self.topVisibleMessage]; self.cellOffset = self.tableView.contentOffset.y - topIndexPath.row * [self firstRowHeight]; } -(void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.tableView reloadData]; if (self.topVisibleMessage) { NSIndexPath *topIndexPath = [self.fetchedResultsController indexPathForObject:self.topVisibleMessage]; CGPoint point = {0, topIndexPath.row * [self firstRowHeight] + self.cellOffset}; [self.tableView setContentOffset:point]; } } 

Su tarea tal vez esté familiarizada con muchas vistas de la list de aplicaciones de noticias. ¿Te fijaste en esas aplicaciones? Pueden tener algún tipo de soluciones. Como sé, la única forma de mantener la position de vista de tabla es scrollRectToVisible:animated:

Muchas aplicaciones de networkinges sociales tienen un enfoque familiar para insert nuevas celdas en la parte superior. Cuando hay actualizaciones, aparece una pequeña notificación en la parte superior de la vista con el post ("5 elementos nuevos"), que al toque inserta las celdas y los desplazamientos automáticos hacia la parte superior.