2012-06-30 29 views
9

he obtenido un UITableView que se llena con una cantidad desconocida de filas. Cada fila contiene (por ejemplo, 3) imágenes y la aplicación reúne esta información de un servicio web.UITableView con desplazamiento infite y carga diferida

Para el UITableView he implementado desplazamiento infinito. Cada vez que la tabla casi llega al final de la cantidad actual de filas, inicio una llamada al servicio web para buscar las siguientes 50 filas de datos. Lo hago en el método scrollViewDidScroll que es llamado por UITableView.

- (void) scrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    CGFloat actualPosition = scrollView.contentOffset.y; 

    float bottomOffset = 450; 
    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) 
     bottomOffset = 1000; 

    CGFloat contentHeight = scrollView.contentSize.height - bottomOffset; 
    if (actualPosition >= contentHeight && !_loading && !_cantLoadMore) 
    { 
     self.loading = YES; 

     _currentPage++; 

     NSMutableDictionary* dict = [[NSMutableDictionary alloc] init]; 
     [dict setObject:[NSNumber numberWithInt:_currentPage] forKey:@"page"]; 
     [dict setObject:[_category objectForKey:@"ID"] forKey:@"category"]; 

     [self performSelectorInBackground:@selector(getWallpapersInBackground:) withObject:dict]; 
    } 
} 

Las imágenes en las filas de la UITableView son perezosos cargado. Cada vez que se ve una fila, las imágenes se cargan en un hilo separado y las filas se actualizan una vez que la imagen se descarga por completo. El principio que uso para la carga diferida es el mismo que Apple sugiere en su documentación. La imagen también se agrega a un NSDictionary local, por lo que puedo buscarla cuando la fila se desplaza fuera de la pantalla y vuelve a aparecer (y la fila se vuelve a crear).

Como la cantidad de imágenes en una sola vista puede llegar hasta 2000 - 3000, también guardo en caché las imágenes en el disco y elimino las imágenes del NSDictionary cuando están más allá de X filas. Cuando el usuario se desplaza de nuevo hacia arriba y abajo ocurre lo siguiente:

  1. nuevas filas se muestran
  2. método de carga perezosa se llama, que comprueba si la imagen está presente en el disco o que deben descargarlo.
  3. Cuando la imagen se descarga o se obtiene del disco, realiza un bloque de código, que muestra la imagen en la fila. Las imágenes descargadas de Internet también se almacenan en caché en el disco.
  4. UIImage se agrega a NSDictionary para un almacenamiento en caché más rápido de las imágenes que deben estar a su alcance.
  5. Las imágenes que están en filas, 15 filas o más lejos de las filas visibles se eliminan del NSDictionary, debido a problemas de memoria (demasiados UIImage objetos en el NSDictionary causan errores de falta de memoria).

Cuando el UITableView casi alcanza el final, ocurre lo siguiente:

  1. UITableView casi llega al final de filas cargados actualmente
  2. llamada a servicio web, con un montón de nuevas filas (50)
  3. Las nuevas filas se agregan a una matriz, que se utiliza para el método numberOfItemsInSection.
  4. Se llama a reloadData para asegurarse de que UITableView se rellene con las filas nuevas adicionales.
  5. Las nuevas filas que contienen imágenes, realizan los pasos mencionados anteriormente para cargar las imágenes de forma perezosa.

Entonces, el problema que tengo es cuando agrego nuevos registros del servicio web. Cuando llamo a reloadData en el UITableView, algunas imágenes vuelven a cargarse desde el disco y se producen algunas fluctuaciones mientras se desplaza.

Estoy buscando una solución para esto.Traté de usar insertItemsAtIndexPaths con la cantidad de nuevas filas, para agregarlas al UITableView, pero esto hace que mi método de carga lenta ya descargue las imágenes (porque de alguna manera todas las celdas se crean en ese momento, incluso cuando no son visibles, verificando si la celda es visible durante la creación brinda resultados inesperados, las imágenes no se cargan, las células se ven raras, etc.).

Por lo tanto, lo que busco esencialmente es una solución para un infinito desplazamiento de UITableView, que carga imágenes de la web/disco y es tan suave como la aplicación de fotos. Como las imágenes están todas cargadas en hilos separados, no entiendo por qué el desplazamiento no es tan suave como la piel de un bebé.

+0

[KTPhotoBrowser] (https://github.com/kirbyt/KTPhotoBrowser) es una muy buena biblioteca para la navegación, la descarga y el almacenamiento en caché de fotos. Puede modificarlo para que se ajuste a sus necesidades. – Hejazi

Respuesta

13

No estoy seguro de si entiendo completamente la plenitud de su pregunta, pero he aquí algunas cosas que hice cuando me enfrenté a un problema similar.

  • He utilizado -tableView:cellForRowAtIndexPath: como mi referencia para cargar más datos de la web. Escogí un número (en mi caso 10), cuando indexPath.row + 10 >= self.data.count carga más datos.

    • Necesitaba llamar al -tableView:cellForRowAtIndexPath: de todos modos.
    • No forcé una devolución de llamada en el bucle más apretado de -scrollViewDidScroll:.
  • I subclases UIImageView con una clase que asíncrono cargar imágenes que llamé URLImageView.

    • En -tableView:cellForRowAtIndexPath:, que asigna una dirección URL a la URLImageView ejemplo.
    • Esa asignación provocó una operación en segundo plano que se cargaría desde el disco o se cargaría desde la web.
    • La operación fue cancelable, por lo que no seguí trabajando en una imagen que ya no necesitaba cargar.

que tenía una vista de tabla con cientos (pero no miles) de imágenes. Solo tenía 2 o 3 celdas de tabla en la pantalla a la vez.

  • utilicé -refreshData: trabajó como un campeón.
  • Incluso obtuve URLImageView para desvanecerse en la imagen. Fue un efecto muy agradable.

Espero que ayude.

+0

puede por favor elaborar un poco ... estoy enfrentando el mismo problema .. – Rakesh

+0

No estoy seguro de lo que quiere elaborado? En '-tableView: cellForRowAtIndexPath:', 'if (indexPath.row + 10> = self.data.count) {[self.data loadNextChunkWithCompletion:^{[tableView reloadData]; }]; } ', donde' self.data' es un modelo de datos que tiene los datos parcialmente cargados y '-loadNextChunkWithCompletion:' es un método que carga la siguiente parte de los datos. –

2

para evitar el parpadeo intente llamar a beginUpdates en la tabla, luego insertrowAtIndexPaths:withRowAnimations: y termine con endUpdates.

Buena suerte.