UITableView - change the image of the cell when scrolling

Hi, my problem is that when scrolling through the TableView, the image will appear in the wrong cell, after a few seconds the correct image will appear.

here is my code

- (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; } 

Please help me

+5
source share
6 answers

You can try adding the following code to your cellForRowAtIndexPath -

1) Assign an index value to your custom cell. For instance,

 cell.tag = indexPath.row 

2) In the main thread, before assigning the image, check whether the image belongs to the corresponding cell by matching it with the tag.

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

You reuse old cells, which is good. However, you do not initialize the image as a cell image, which is not very good. What you are describing is due to the fact that the old cell with the image that was already loaded for that cell is used for the new cell. Then you download this cell image in the background (which is good again), but it takes a few seconds for this image. In the meantime, an image that has already been uploaded to the old cell is displayed (and that the reason you see the wrong image in this cell is for a few moments).

Decision? add either

 thumbnailImageView.image = nil 

or

 thumbnailImageView.image = someDefaultImageWhileYourRealOneLoads 

before dispatch_queue_t concurrentQueue ...

Thus, you will not see the old (irrelevant) image while the real one is loading.

Hope this helps. Good luck.

+5
source

Like your ImageView, a dispatch call is loaded into async , which is NOT in the main thread and called in some other thread, so there is a delay in receiving data from the URL, and then converting it to UIImage. This process takes a little time, as you know, but you scroll through the table view faster. And, as you know, cellForRowAtIndexPath reuses any cell that is outside the window, so a cell that is reused may NOT retrieve images that you would have previously done when they were in the window. Thus, it loads the wrong data, and then again, when async starts for this particular cell, the cell loads this image, but there is a delay.

To overcome this feature, since Chronch pointed it out, you can leave the image as zero OR you can use AFNetworking own UIImageView, which has an excellent class for loading image images quite elegantly

I will leave a link to it AFNetworking

+3
source

I would do all the data binding in - tableView: willDisplayCell: forRowAtIndexPath: just because your cell is not drawn on cellForRowAtIndexPath yet. Another solution you can use is AFNetworking, like someone else mentioned above me.

+1
source

Swift 3.0

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

Don't worry, add two lines and feel free.

  cell.thumbnailimages.image=nil cell.thumbnailimages.setImageWith(imageurl!) 

I think these two lines solve your problem. Thanks at Advance

0
source

All Articles