在单元格中异步加载图像的 UITableView - 图像在慢速连接时不断变化

UITableView with asynchronous loading of image in cells - images keep changing on slow connection

我正在 table 视图中异步加载图像。在连接速度较慢时,单元格中的图像保持 flickering/changing(我假设它来自重复使用单元格)。我听从了其他一些相关问题的建议,包括:

在正常连接上没有问题,但是在EDGE和慢速网络上,问题仍然存在。我想知道是否正在使用网络请求备份全局队列?如果是这样,我该如何解决?

这是我的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // get the data for this photo post
    NSDictionary *data = [self.streamPhotosData objectAtIndex:indexPath.row];

    static NSString *CellIdentifier = @"StreamPhotoTableViewCell";
    __block StreamPhotoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"StreamPhotoTableViewCell"];

    if (cell == nil) {
        cell = [[StreamPhotoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    cell.delegate = self;

    // check if image in cache, else cache it
    if ([[[GlobalCaches getCurrentInstance] photoCache] objectForKey:[data objectForKey:@"photoGuid"]] != nil) {
        // cache hit
        cell.photoImageView.image = [[[GlobalCaches getCurrentInstance] photoCache] objectForKey:[data objectForKey:@"photoGuid"]];
    } else {
        // set a placeholder image
        cell.photoImageView.image = [UIImage imageNamed:@"placeholder.png"];

        // download the image asynchronously
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
            UIImage *downloadedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[data objectForKey:@"url"]]]];

            if (downloadedImage) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    cell.photoImageView.image = downloadedImage;

                    // update cache
                    [[[GlobalCaches getCurrentInstance] photoCache] setObject:downloadedImage forKey:[data objectForKey:@"photoGuid"]];
                });
            }
        });

    }

    return cell;
}

我曾经遇到过类似的问题。

为什么会这样? 假设您在第 1 行的 cellForRow 中,此图像不在缓存中,因此您正在下载它。同时,您滚动 tableView,假设现在您在 cellForRow 中的第 8 行,这是同一个单元格实例。 假设现在缓存中有此图像,所以您只需设置没有时间偏移的图像,并且在单元格包含正确的图像后,第 1 行的图像已准备就绪,请记住它是相同的单元格实例,因此图像将被替换。 当然这只是一个例子。

你可以试试'remember'你从哪一行开始下载图片,在开始下载之前设置一个'beforeTag',然后是,检查如果相同indexPath.row

    NSInteger beforeTag = indexPath.row;

    // download the image asynchronously
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
        UIImage *downloadedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[data objectForKey:@"url"]]]];

        if (downloadedImage) {
            dispatch_async(dispatch_get_main_queue(), ^{

                if (indexPath.row == beforeTag) {
                    cell.photoImageView.image = downloadedImage;
                }

                // update cache
                [[[GlobalCaches getCurrentInstance] photoCache] setObject:downloadedImage forKey:[data objectForKey:@"photoGuid"]];
            });
        }
    });

此外,我会将这一行放在您自定义单元格的 prepareForReuse 中:

cell.photoImageView.image = [UIImage imageNamed:@"placeholder.png"];

每次重用 UITableViewCell 时都会调用此方法,它会在您“dequeueReusableCellWithIdentifier”之后调用,如果单元格已经存在。并且总是放一个占位符图像是可以的,如果图像在缓存中,你不会注意到这个占位符。

希望对您有所帮助