Reputation: 5
I'm trying to create a feed just like the one in facebook. The problem is, the image on the succeeding rows will load the images from the initial rows and then correctly load their corresponding load. When you go to the top rows, the images previously loaded are gone. I've tried lazy loading but the problem persists. You could view the video to understand the problem better. (https://www.youtube.com/watch?v=NbgYM-1xYN4)
The images are asynchronously loaded and are fetched from our server.
Here are some Code:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [latestPosts count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary * dataDict = [latestPosts objectAtIndex:indexPath.row];
CardCell *cell = [self.feedTable dequeueReusableCellWithIdentifier:@"CardCell"];
if (cell == nil) {
cell = [[CardCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CardCell"];
}
[cell layoutSubviews];
NSURL *imageURL = [[NSURL alloc] initWithString:[dataDict objectForKey:@"post_holder_image"]];
NSURL *postImageURL = [[NSURL alloc] initWithString:[dataDict objectForKey:@"post_image"]];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
NSData *postImageData = [NSData dataWithContentsOfURL:postImageURL];
dispatch_async(dispatch_get_main_queue(), ^{
cell.brandImage.image = [UIImage imageWithData:imageData];
cell.postImage.image = [UIImage imageWithData:postImageData];
});
});
cell.brandName.text = [dataDict objectForKey:@"post_holder"];
cell.postDateTime.text = [dataDict objectForKey:@"post_datetime"];
cell.postMessage.text = [dataDict objectForKey:@"post_content"];
return cell;
}
Upvotes: 0
Views: 1725
Reputation: 8579
There are a few problems with the above.
As mentioned above you need to use a image as a placeholder (i.e blank white or an image of your choice) in the cell init code AND cell reuse.
You really need to cache your images, only download an image once and then store it in a dictionary. i.e.:
UIImage *cachedImage = self.images[user[@"username"]];
if (cachedImage) {
//use cached image
[button setBackgroundImage:cachedImage forState:UIControlStateNormal];
}
else {
//download image and then add it to the dictionary }
where self.images
is an NSMutableDictionary
. You could also look into NSCache
. If you don't cache the images you will find the table is very laggy when scrolling for a large number of rows because of the image conversion from data.
However this will not completely fix the problem if you start loading a table and scroll up and down very fast the images will appear to be in the wrong places and move around until they are all loaded. Cell reuse will confuse where to put the image. Make sure you put [tableView reloadItemsAtIndexPaths:@[indexPath]];
in your download block i.e.:
NSURL *imageURL = [[NSURL alloc] initWithString:[dataDict objectForKey:@"post_holder_image"]];
NSURL *postImageURL = [[NSURL alloc] initWithString:[dataDict objectForKey:@"post_image"]];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
NSData *postImageData = [NSData dataWithContentsOfURL:postImageURL];
dispatch_async(dispatch_get_main_queue(), ^{
cell.brandImage.image = [UIImage imageWithData:imageData];
cell.postImage.image = [UIImage imageWithData:postImageData];
[tableView reloadItemsAtIndexPaths:@[indexPath]];
});
});
Upvotes: 1
Reputation: 135
You need to set imageview.image nil or you should set your placeholder image while reusing cells. Here is same question Async image loading from url inside a UITableView cell - image changes to wrong image while scrolling Other than that if you are not using parse.com api ect. you can check https://github.com/rs/SDWebImage or https://github.com/AFNetworking/AFNetworking There are tons of answer about this topic.
[cell layoutSubviews];
cell.brandImage.image = nil;
cell.postImage.image = nil;
Upvotes: 0
Reputation: 159
Use below method of UITableViewCell in your custom cell and set the image property to nil.
hope it will work for you.
-(void)prepareForReuse{
[super prepareForReuse];
// Then Reset here back to default values that you want.
}
Upvotes: 2