setImageWithUrl显示缓存图像时出现白色闪烁

时间:2014-03-27 11:22:15

标签: ios image caching afnetworking afnetworking-2

使用AFNetworking 2.0的方法setImageWithUrl,我在位于UITableViewCell中的imageView中设置了一个图像。首次下载然后设置显示的图像时,它可以正常工作。但是,如果图像在设置时在本地可用(已缓存),则在显示之前会有一个快速的白色闪光。

你知道如何避免这种情况吗?

重现的步骤:

  1. 设置图像(图像将被缓存)
  2. 关闭申请
  3. 启动申请
  4. 设置(现在缓存的)图片
  5. 设置图像的代码:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
        myCell *cell = (myCell *)[tableView dequeueReusableCellWithIdentifier:@"imageCell"];
    
        [cell.myImageView setImageWithURLRequest:[NSURLRequest requestWithURL:myImageUrl] placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
            cell.myImageView.image = image;
    
        } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
            NSLog(@"Failed");
        }];
    
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        return cell;  
    }
    

3 个答案:

答案 0 :(得分:7)

如果有人碰到同样的问题,我就是这样解决的:

在成功阻止中,替换

cell.myImageView.image = image;

if (request) {
    [UIView transitionWithView:cell.myImageView
                      duration:0.8f
                       options:UIViewAnimationOptionTransitionCrossDissolve
                    animations:^{[cell.myImageView setImage:image];}
                    completion:NULL];
}else{
    [cell.myImageView setImageWithURL:myImageURL];
}

Voilà,不再是丑陋的闪光!

this answer致使我走上正轨。

答案 1 :(得分:0)

您的问题似乎与细胞重用有关,而与缓存问题有关。

当您重复使用单元格时(滚动UITableView或重新打开应用程序时),它们会保留对旧图像的引用。当您将nil传递给placeholderImage参数时,AFNetworking不会重置您的图片。这是source code。因此,新图像设置在success块中。但是在稍微网络延迟之后可能会调用此块以使图像闪烁。顺便说一句,您可以省略成功区块,以便AFNetworking set the image by itself

如果您没有placeHolder图片,则应在尝试异步设置新图片之前将myImageView.image设置为nil

此外,您应该检查dequeueReusableCellWithIdentifier:方法是否返回一个单元格,如果没有,则创建一个新单元格。第一次创建UITableView时可能会发生这种情况。

以下是一个例子:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    myCell *cell = (myCell *)[tableView dequeueReusableCellWithIdentifier:@"imageCell"];

    // Check if reused cell was returned.
    // If not create a new one, otherwise, reset the state of the reused cell
    if (!cell) {
        cell = [[myCell alloc] init];
    } else {
        cell.myImageView.image = nil;
    }

    [cell.myImageView
        setImageWithURLRequest:[NSURLRequest requestWithURL:myImageUrl]
        placeholderImage:nil
        success:nil
        failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
            NSLog(@"Failed");
        }];

    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    return cell;  
}

答案 2 :(得分:0)

您需要这样的功能:

BOOL ImageDataHasPNGPreffix(NSData *data) {
NSUInteger pngSignatureLength = [kPNGSignatureData length];
if ([data length] >= pngSignatureLength) {
    if ([[data subdataWithRange:NSMakeRange(0, pngSignatureLength)] isEqualToData:kPNGSignatureData]) {
        return YES;
    }
}

return NO;
}

然后,当您保存数据时,您需要选择正确的缓存方式

//Saving data
if ([imageData length] >= [kPNGSignatureData length]) {
    imageIsPng = ImageDataHasPNGPreffix(imageData);
}

if (imageIsPng) {
    data = UIImagePNGRepresentation(image);
}
else {
    data = UIImageJPEGRepresentation(image, (CGFloat)1.0);
}