UITableView: imágenes de celdas que cambian mientras se desplaza

Hola, mi problema es que cuando desploop a TableView, la image aparecerá en una celda incorrecta, luego de unos segundos aparece la image correcta.

aquí está mi código

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; // Configure the cell... if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ; } [cell setOpaque:NO]; [cell setBackgroundColor: [UIColor clearColor]]; PlaceData *data = [tableData objectAtIndex:indexPath.row]; UILabel *nameLabel = (UILabel *)[cell viewWithTag:100]; UILabel *sciNameLabel = (UILabel *)[cell viewWithTag:200]; UIImageView *thumbnailImageView = (UIImageView *)[cell viewWithTag:300]; nameLabel.text = data.name; sciNameLabel.text = data.scientific_name; // get a dispatch queue dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // this will start the image loading in bg dispatch_async(concurrentQueue, ^{ NSURL *urlToPicture = [NSURL URLWithString:[NSString stringWithFormat:@"%@", data.thumbnail]]; NSData *imgData = [NSData dataWithContentsOfURL:urlToPicture options:0 error:nil]; // This will set the image when loading is finished dispatch_async(dispatch_get_main_queue(), ^{ UIImage *tmpImage = [[UIImage alloc] initWithData:imgData]; thumbnailImageView.image = tmpImage; //dispatch_release(concurrentQueue); }); }); return cell; } 

por favor, ayúdame

Puede intentar agregar el siguiente código a su cellForRowAtIndexPath:

1) Asigne un valor de índice a su celda personalizada. Por ejemplo,

 cell.tag = indexPath.row 

2) En el subprocess principal, antes de asignar la image, verifique si la image pertenece a la celda correspondiente al emparejarla con la label.

 dispatch_async(dispatch_get_main_queue(), ^{ if(cell.tag == indexPath.row) { UIImage *tmpImage = [[UIImage alloc] initWithData:imgData]; thumbnailImageView.image = tmpImage; }}); }); 

Estás reutilizando celdas viejas, lo cual es bueno. Sin embargo, no está inicializando la image en la vista de image de la celda, lo que no es tan bueno. Lo que está describiendo sucede porque una celda antigua, con una image que ya estaba cargada para esa celda, se usa para la celda nueva. Luego está cargando la image de esa celda en segundo plano (que, una vez más, es buena), pero tarda unos minutos en cargarse completamente esa image. Mientras tanto, se muestra la image que ya estaba cargada en la celda anterior (y esa es la razón por la que está viendo una image incorrecta en esa celda, por unos momentos).

¿La solución? agregar ya sea

 thumbnailImageView.image = nil 

o

 thumbnailImageView.image = someDefaultImageWhileYourRealOneLoads 

justo antes de dispatch_queue_t concurrentQueue ...

De esa forma, no verá la image antigua (irrelevante) mientras se carga la real.

Espero que esto ayude. Buena suerte.

Como se debe cargar su ImageView en una llamada de envío async que NO está en el hilo principal y se está invocando en otro hilo así que hay un retraso en la obtención de los datos de la URL y luego convertirlos a un UIImage. Este process toma un poco de time como lo sabes, pero estás desplazando la vista de tabla a una velocidad más rápida. Y como sabes, cellForRowAtIndexPath reutiliza cualquier celda que se encuentre fuera de la window, por lo que la celda que se está reutilizando podría NO get la imagedata que era RECUPERAR previamente cuando estaba en la window. Por lo tanto, carga los datos incorrectos y, una vez más, cuando se dispara un async para esa celda específica, la celda carga esa image pero llega el retraso.

Para superar esta function como lo señaló Chronch, puede dejar la vista de image como nula O puede usar la propia categoría UIImageView de AFNetworking que tiene una class excelente para cargar imágenes con bastante elegante apariencia

Dejaré un enlace AFNetworking

Haría todos mis datos bindings en – tableView: willDisplayCell: forRowAtIndexPath: solo porque en cellForRowAtIndexPath su celda aún no se ha dibujado. Otra solución que puede usar es AFNetworking como alguien más mencionado antes que yo.

Swift 3.0

 DispatchQueue.main.async(execute: {() -> Void in if cell.tag == indexPath.row { var tmpImage = UIImage(data: imgData) thumbnailImageView.image = tmpImage } })