2011-05-24 25 views
8

Siempre que llamoreloadRowsAtIndexPaths Calling elimina tableView contentOffset

reloadRowsAtIndexPaths 

Mi UITableView contentOffset se retira, ¿existe un método delegado que puedo utilizar para atrapar la vista de tabla de actualización y establecer el offset de nuevo de modo que permanezca en su lugar y no anima a la vista, o simplemente evita que lo haga?

estoy fijando la contentOffest en viewDidLoad:

Aquí es un ejemplo de uso:

[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:[params valueForKey:@"index"], nil] withRowAnimation:UITableViewRowAnimationFade]; 

Que elimina la contentOffset y la anima a la vista, lo que no quiero.

Más específicamente, esto parece ocurrir cuando la fila que se está recargando está en indexPath.section 0 y indexPath.row 0, es decir, la fila superior.


Más información

Estoy llamando reloadRowsAtIndexPaths después de una solicitud asincrónica a buscar una imagen de un servidor. Básicamente funciona así:

  • cellForRowAtIndexPath se llama el que comprueba la presencia del archivo pulgar en el disco, si el archivo no está presente se carga un marcador de posición en su lugar y una solicitud asincrónica se inicia en un fondo hilo para recuperar la imagen.
  • Cuando la descarga de la imagen se ha completado, llamo al reloadRowsAtIndexPaths para obtener la celda correcta, de modo que la imagen correcta se desvanezca en lugar de la imagen del marcador de posición.
  • La cantidad de células puede ser diferente que la solicitud se llama el interior cellForRowAtIndexPath para que las imágenes se cargan en la medida que la carga células

comprobación del archivo cellForRowAtIndexPath

paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
path = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_small.gif",[[listItems objectAtIndex:indexPath.row] valueForKey:@"slug"]]]; 

    if([[NSFileManager defaultManager] fileExistsAtPath:path]){ 

     listCell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:path]]; 

    } else { 

     listCell.imageView.image = [UIImage imageNamed:@"small_placeholder.gif"]; 

     NSMutableDictionary *params = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[[[listItems objectAtIndex:indexPath.row] valueForKey:@"image"] valueForKey:@"small"],@"image",[NSString stringWithFormat:@"%@_small.gif",[[listItems objectAtIndex:indexPath.row] valueForKey:@"slug"]], @"name",indexPath,@"index",@"listFileComplete",@"notification",nil]; 

     [NSThread detachNewThreadSelector:@selector(loadImages:) toTarget:self withObject:params]; 

     [params release]; 

    } 

Archivo donwloaded notificación:

-(void)fileComplete:(NSNotification *)notification { 

    [self performSelectorOnMainThread:@selector(reloadMainThread:) withObject:[notification userInfo] waitUntilDone:NO]; 
} 

recarga celular (He hardcoded secciones debido a un error con los números de sección extraños que se pasa muy raramente causar un accidente:

-(void)reloadMainThread:(NSDictionary *)params { 

    NSIndexPath *index; 

    switch ([[params valueForKey:@"index"] section]) { 
     case 0: 
      index = [NSIndexPath indexPathForRow:[[params valueForKey:@"index"] row] inSection:0]; 
      [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:[params valueForKey:@"index"], nil] withRowAnimation:UITableViewRowAnimationNone]; 
      break; 
     default: 
      index = [NSIndexPath indexPathForRow:[[params valueForKey:@"index"] row] inSection:2]; 
      [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:index,nil] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 

} 

Respuesta

2

EDIT: Mi respuesta original no se han centrado en el problema central

¿Está cambiando el número de filas antes de la llamada al reloadRows...? reloadRows... es específicamente para animar un cambio de valor, por lo que el código debe ser algo como esto:

UICell *cell = [self cellForRowAtIndexPath:indexPath]; 
cell.label.text = @"Something new"; 
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]]; 

es que más o menos lo que parece, pero el tableview es olvidar dónde está?


discusión anterior

No llamas -beginUpdates y -endUpdates alrededor de una recarga. Llame al -beginUpdates y al -endUpdates en relación con las modificaciones relacionadas de los datos de respaldo, durante las cuales debe llamar al -insertRowsAtIndexPaths:withRowAnimation: y a sus familiares. Si llama a las rutinas de actualización, entonces no necesita llamar a las rutinas de recarga. Recargar en medio de una actualización es un comportamiento indefinido.

Consulte Batch Insertion, Deletion, and Reloading of Rows and Sections para obtener detalles sobre cuándo utiliza -beginUpdates.

+0

Gracias por la sugerencia, supongo que mi problema es con reloadRowsAtIndexPaths y no beginUpdates ya que el problema todavía existe con begin/end eliminado – Alex

+0

Editado; Puede que haya entendido mal el aspecto del resto del código. –

+0

He actualizado mi pregunta para dar más información sobre mi problema – Alex

0

Ha intentado lo siguiente:

CGPoint offset = [self.tableView contentOffset]; 
CGSize size = [self.tableView contentSize]; 

CGFloat percentScrolled = offset.y/size.height; 

// call reloadRowsAtIndexPaths, inserts, deletes etc. 
// ... 

CGSize newSize = [self.tableView contentSize]; 
CGSize newOffset = CGPointMake(0, newSize.height * percentScrolled); 

[self.tableView setContentOffset:newOffset animated:NO]; 

esto parece un poco demasiado trivial, no estoy seguro de que funcionaría, pero merece la pena intentarlo.

+0

Esto funcionaría muy bien si no detuviera el desplazamiento de la tabla View – Alex

0

Reemplazar

[_tableView reloadData]; 

con

[_tableView reloadRowsAtIndexPaths:...withRowAnimation:...]; 

y que será bueno.

3

Parece que está teniendo este problema debido a las alturas de fila estimadas incorrectamente. Debido a que (por algún motivo misterioso) la vista de tabla determina el nuevo desplazamiento después de volver a cargar algunas celdas con la altura de fila estimada, debe asegurarse de que el tableView:estimatedHeightForRowAtIndexPath devuelva datos correctos para las celdas que ya se han procesado. Para lograr esto se podría almacenar en caché los altos de fila visto en un diccionario:

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
    heightForIndexPath[indexPath] = cell.frame.height 
} 

continuación, utilizar estos datos correctos o su estimación para las células no ya cargados:

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 
    return heightForIndexPath[indexPath] ?? averageRowHeight 
} 

(Muchísimas gracias a eyuelt para la visión que la altura estimada fila se utiliza para determinar el nuevo desplazamiento)

+0

Wowowowow! La mejor respuesta, ¡me gustaría haberla votado 10 veces! Muchas gracias, Daniel, espero que en el futuro encuentres una de mis respuestas tan útil como la tuya ahora. – ingaham

+0

Wowwwwwwwwwwwwwww .... busco una solución a mi problema de superposición de células y esta respuesta APARECE lo he resuelto ¡Mucho amor, Daniel! –

0

yo uso este:.

-(void)keepTableviewContentOffSetCell:(cellClass *)cell{ 
    CGRect rect = cell.frame; 
    self.tableView.estimatedRowHeight = rect.size.height ; 
} 

Puede usarlo antes de volver a cargar la celda. La vista de tabla no se desplazará cuando vuelva a cargar la celda.

Cuestiones relacionadas