2012-02-08 18 views
5

necesito cargar desde la web/archivos algunos UIImages. Yo estaba buscando y me encontré en otra question este código:UITableViewCell carga imágenes y celdas reutilizadas

if (![[NSFileManager defaultManager] fileExistsAtPath:user.image]) { 
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 
     dispatch_async(queue, ^{ 
      NSData *imageData =[NSData dataWithContentsOfURL:[NSURL URLWithString:user.imageURL]]; 

      [imageData writeToFile:user.image atomically:YES]; 
      dispatch_sync(dispatch_get_main_queue(), ^{ 
       UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 
       UIImage *image = [UIImage imageWithData:imageData]; 
       [self.imageFriends setObject:image forKey:[NSNumber numberWithInt:user.userId]]; 
       cell.imageView.image = image; 
       [cell setNeedsLayout]; 
       NSLog(@"Download %@",user.image); 
      }); 
     }); 
     cell.imageView.image=[UIImage imageNamed:@"xger86x.jpg"]; 
    } else { 
     NSLog(@"cache"); 
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 
     dispatch_async(queue, ^{ 
      UIImage *image = [UIImage imageWithContentsOfFile:user.image]; 
      //[self.imageFriends setObject:image forKey:[NSNumber numberWithInt:user.userId]]; 
      dispatch_sync(dispatch_get_main_queue(), ^{ 
       UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath]; 
       newCell.imageView.image=image; 
       [newCell setNeedsLayout]; 
      }); 
     }); 
    } 

Pero el problema es que cuando me desplazarse rápidamente hacia la parte superior o inferior de las imágenes se cargan mal y hay un corto retraso cuando termina.

Entonces la pregunta es ... ¿cómo puedo cargar los UIImages en la celda correcta cuando utilizo colas para buscarlos? ¡Gracias!

Respuesta

7

sospecho que las imágenes incorrectas que se ven son el resultado de no establecer su imagen marcador de posición en caso de que tenga una copia local de una imagen, pero todavía la recuperación de lo local copia asincrónicamente Además, en el código que adjuntó para cargar la copia local utiliza UIImage un componente UIKit en una cadena de fondo.

También, curiosamente, parece que está haciendo algún tipo de almacenamiento en caché UIImage. Agregar las imágenes a lo que supongo es una propiedad NSMutableArray llamada imageFriends. Pero parece que ha comentado el complemento de caché en caso de que tenga una copia local del archivo. Además, su código publicado nunca usa el UIImages en caché.

Mientras 2 niveles de almacenamiento en caché parece un poco por la borda si se quería hacer esto usted podría hacer algo como esto:

UIImage *userImage = [self.imageFriends objectForKey:[NSNumber numberWithInt:user.userId]]; 
if (userImage) { // if the dictionary of images has it just display it 
    cell.imageView.image = userImage; 
} 
else { 
    cell.imageView.image = [UIImage imageNamed:@"xger86x.jpg"]; // set placeholder image 
    BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:user.image]; 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     NSData *imageData = nil; 
     if (fileExists){ 
      imageData = [NSData dataWithContentsOfFile:user.image]; 
     } 
     else { 
      imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:user.imageURL]]; 
      [imageData writeToFile:user.image atomically:YES]; 
     } 
     if (imageData){ 
      dispatch_async(dispatch_get_main_queue(), ^{ 
        // UIKit, which includes UIImage warns about not being thread safe 
        // So we switch to main thread to instantiate image 
       UIImage *image = [UIImage imageWithData:imageData]; 
       [self.imageFriends setObject:image forKey:[NSNumber numberWithInt:user.userId]]; 
       UITableViewCell *lookedUpCell = [tableView cellForRowAtIndexPath:indexPath]; 
       if (lookedUpCell){ 
        lookedUpCell.imageView.image = image; 
        [lookedUpCell setNeedsLayout]; 
       } 
      }); 
     } 
    }); 
} 

UIImage s son parte de UIKit y no seguro para subprocesos. Pero puede cargar el NSData en otro hilo.

+0

La nota acerca de que UIImage no era seguro para la ejecución de hilos era la clave de un problema que estaba tratando de resolver. – JamesSwift

6

Está cargando la imagen de forma asíncrona, por lo que durante el desplazamiento rápido las celdas se reutilizan más rápido y luego se descargan las imágenes. Una forma de evitar cargar una imagen incorrecta sería verificar si la celda ya se reutilizó cuando se cargó la imagen. O cancele todas las solicitudes en curso cuando dequeue nuevas celdas.

También recomendaría mirar AFNetworking, ya que contiene la categoría útil para UIImageView, por lo que puedo hacer algo como esto:

[imageView setImageWithURL:[NSURL URLWithString:@"http://i.imgur.com/r4uwx.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder-avatar"]]; 

También contiene cancelImageRequestOperation método, para cancelar las solicitudes en curso. A continuación, el código se vería así:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
if (cell == nil) { 
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
} else { 
    [cell.imageView cancelImageRequestOperation]; 
} 
[cell.imageView setImageWithURL:[NSURL URLWithString:user.imageURL] placeholderImage:[UIImage imageNamed:@"xger86x.jpg"]]; 
Cuestiones relacionadas