Uitableviewcell Subclass Wrong Image in Cell or Old Image Bug

UITableViewCell subclass wrong image in cell or old image bug

I recommend you to use 3rd party library to load image with url such as Kingfisher. It will handle caching and cancel loading for you.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = dataSource[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "Identifier") as! ACell
cell.update(data)
return cell
}

And the cell will look like this.

import Kingfisher
class ACell: UITableViewCell {
@IBOutlet fileprivate weak var backgroundImageView: UIImageView!

fileprivate func reset() {
backgroundImageView.image = nil
}

func update(_ data: ATypeOfData) {
reset()
let resource = ImageResource(downloadURL: url)
backgroundImageView.kf.setImage(with: resource)
}
}

The reason you are failing is you misunderstood reusing cell.

let updateCell = tableView.cellForRow(at: indexPath)

The updateCell can be a different cell with a cell which you want to use. It can be just a reused random cell. If you really want to track a cell, you need to set a property and check the property in cellForRowAt is same as the property in your image loading closure. I really recommend you to use the pattern I attached.

Images in UITableViewCells are loading wrong

The table view cells are being reused for performance reason, so they will retain the previously used image in the UIImageView if you do not set it to anything before you load the image.

Right before you call the startLoadingImageWithUrl, you can set the initial image of the imageView with a placeholder image first or maybe add loading indicator on top of the imageView. But remember to remove the loading indicator when the real image is loaded.

- (void) startLoadingImageWithUrl:(NSString *)urlString forItem:(id)item
{
UIImageView *imageView = ((UIImageView*)[((UIView*)item)viewWithTag:100]);
imageView.image = placeholderImage;
if (self.cacheStoreDictionary[urlString]) {
UIImage *image = self.cacheStoreDictionary[urlString];
[self.delegate lcCachedImageLoader:self didLoadImage:image forItem:item wasCacheHit:YES];
} else {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
[self.cacheStoreDictionary setObject:image forKey:urlString];
[self.delegate lcCachedImageLoader:self didLoadImage:image forItem:item wasCacheHit:NO];
});
});
}
}

And for the image appearing at the wrong cell after the image is loaded, it is because you are passing item, which is reused cell, as a parameter in the startLoadingImage and didLoadImage. Try to pass indexPath instead and locate the correct cell with the indexPath, the update the cell image view.

UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];

UITableView cell sometimes fails to update image, but displays fine after scroll

Yup, the problem was on my side.

The exact cause was some pretty weird date comparison code. More precisely, this code was failing to call reloadRowsAtIndexPaths: with the right indexes because two cells had identical dates, which resulted in one cell getting updated twice, and one cell not getting updated at all. I'm not referring to the code provided in the question.

My advice to anybody else who runs into the same kind of problem is to carefully check the parts of your code that update and create the cells in your table view.

UITableView dequeued cells reloading old images

Here is what I did using SDWebImage, I was forced to use a placeholder for all cells, I just set the ones without images to a small chevron icon. Works as expected. Thanks everybody.

RSSItem * rssItem = (RSSItem *)(_rssParser.rssItems)[indexPath.row];

if (rssItem.imageURL == nil ){
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
[imageView setImageWithURL:[NSURL URLWithString:rssItem.imageURL] placeholderImage:[UIImage imageNamed:@"chevron.png"]];
cell.accessoryView = imageView;
}else{
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 110, 96)];
imageView.contentMode = UIViewContentModeScaleAspectFit;
[imageView setImageWithURL:[NSURL URLWithString:rssItem.imageURL] placeholderImage:[UIImage imageNamed:@"loading.png"]];
cell.accessoryView = imageView;
}

[cell.textLabel setText:rssItem.title];
[cell.detailTextLabel setText:rssItem.summary];

return cell;

UITableViewCell image not shown until selected

The problem was that my Image wasn't set on the main thread. To solve the problem, I simply used the following code below which ensured that my image will be set immediately.

dispatch_async(dispatch_get_main_queue(), {
// do image functions here

)}

Loading images asynchronously, wrong image in cell

What I ended up doing was subclassing UIImaveView and then passing the image file in cellForRow

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
albumImageCell *cell = (albumImageCell *) [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];

if (cell == nil) {
cell = [[albumImageCell alloc]init];
}

PFObject *temp = [_dataArray objectAtIndex:indexPath.row];
PFFile *file = [temp objectForKey:@"imageThumbnail"];

[cell.imageView setFile:file];

return cell;
}

And then in the customImageView -

- (void) setFile:(PFFile *)file {

NSString *requestURL = file.url; // Save copy of url locally (will not change in block)
[self setUrl:file.url]; // Save copy of url on the instance
self.image = nil;
[file getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
UIImage *image = [UIImage imageWithData:data];
if ([requestURL isEqualToString:self.url]) {
[self setImage:image];
[self setNeedsDisplay];
}
} else {
NSLog(@"Error on fetching file");
}
}];
}

But this gets Data every time the user scrolls to a new cell. So Im still trying to figure out how to match a particular image to a cell, without getting data every time.



Related Topics



Leave a reply



Submit