猿问

使用GCD异步下载UITableView的图像

我正在使用GCD异步下载uitableview的图像,但是有一个问题-滚动图像闪烁并一直更改时。我尝试将每个单元格的图像设置为nil,但这并没有太大帮助。快速向上滚动时,所有图像均不正确。我该怎么办?这是我的细胞方法:


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

}


MMTTMM
浏览 523回答 3
3回答

GCT1015

这里的问题是您的图像获取块正在保存对tableview单元的引用。下载完成后,imageView.image即使您回收了单元格以显示其他行,它也会设置属性。在设置映像之前,您需要下载完成块来测试映像是否仍与单元格相关。还需要注意的是,您不会将图像存储在单元格中以外的任何位置,因此,每次在屏幕上滚动一行时,您都将再次下载它们。您可能希望将它们缓存在某个位置,并在开始下载之前查找本地缓存的图像。编辑:这是使用单元格的tag属性进行测试的简单方法:- (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;}

ibeautiful

关键是您没有完全了解单元重用概念。这与异步下载不太吻合。块    ^{    cell.imageView.image = image;    [cell setNeedsLayout];}在请求完成并且所有数据都已加载时被执行。但是,在创建块时,单元会获得其值。到执行块时,单元仍指向现有单元之一。但是用户很有可能继续滚动。同时,该单元格对象已被重新使用,并且该图像与“ 旧 ”单元格相关联,该单元格已被重用,分配和显示。之后不久,除非用户进一步滚动,否则将加载并分配并显示正确的图像。等等等等。您应该寻找一种更聪明的方法。有很多花絮。Google用于延迟加载图片。

慕侠2389804

使用索引路径获取单元格。如果看不到该单元格nil,则不会有问题。当然,您可能希望在下载数据时缓存数据,以便在已有图像后立即设置单元格的图像。- (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) {                //  You may want to cache this explicitly instead of reloading every time.                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(), ^{                    // Capture the indexPath variable, not the cell variable, and use that                    UITableViewCell *blockCell = [tableView cellForRowAtIndexPath:indexPath];                    blockCell.imageView.image = image;                    [blockCell setNeedsLayout];                });            });        cell.textLabel.text = [self.loader.parsedData[indexPath.row] objectForKey:@"id"];    }    return cell;}
随时随地看视频慕课网APP

相关分类

iOS
我要回答