使用 GCD 异步下载 UITableView 的图像 [英] Asynchronous downloading of images for UITableView with GCD
问题描述
我正在使用 GCD 为我的 uitableview 异步下载图像,但是有一个问题 - 滚动图像时一直闪烁和更改.我尝试将每个单元格的图像设置为 nil,但这并没有多大帮助.快速向上滚动时,所有图像都是错误的.我能做些什么呢?这是我的细胞方法:
I'm downloading images for my uitableview asynchronously using GCD, but there is a problem - when scrolling images flicker and change all the time. I tried setting image to nil with every cell, but it doesn't help much. When scrolling back up fast, all images are wrong. What can I do about that? Here is my method for cells:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (self.loader.parsedData[indexPath.row] != nil)
{
cell.imageView.image = nil;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^(void) {
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[self.loader.parsedData[indexPath.row] objectForKey:@"imageLR"]]];
UIImage* image = [[UIImage alloc] initWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = image;
[cell setNeedsLayout];
});
});
cell.textLabel.text = [self.loader.parsedData[indexPath.row] objectForKey:@"id"];
}
return cell;
}
推荐答案
这里的问题是你的图像获取块持有对 tableview 单元格的引用.下载完成后,它会设置 imageView.image
属性,即使您已回收单元格以显示不同的行.
The problem here is that your image-fetching blocks are holding references to the tableview cells. When the download completes, it sets the imageView.image
property, even if you have recycled the cell to display a different row.
在设置图像之前,您需要下载完成块来测试图像是否仍然与单元格相关.
You'll need your download completion block to test whether the image is still relevant to the cell before setting the image.
还值得注意的是,您不会将图像存储在单元格以外的任何地方,因此每次在屏幕上滚动一行时,您都会再次下载它们.您可能希望将它们缓存在某处并在开始下载之前查找本地缓存的图像.
It's also worth noting that you're not storing the images anywhere other than in the cell, so you'll be downloading them again each time you scroll a row onscreen. You probably want to cache them somewhere and look for locally cached images before starting a download.
这里有一个简单的测试方法,使用单元格的 tag
属性:
here's a simple way to test, using the cell's tag
property:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.tag = indexPath.row;
NSDictionary *parsedData = self.loader.parsedData[indexPath.row];
if (parsedData)
{
cell.imageView.image = nil;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^(void) {
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:parsedData[@"imageLR"]];
UIImage* image = [[UIImage alloc] initWithData:imageData];
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
if (cell.tag == indexPath.row) {
cell.imageView.image = image;
[cell setNeedsLayout];
}
});
}
});
cell.textLabel.text = parsedData[@"id"];
}
return cell;
}
这篇关于使用 GCD 异步下载 UITableView 的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!