【问题标题】:Asynchronously load images from document directory into UICollectionView将文档目录中的图像异步加载到 UICollectionView
【发布时间】:2015-08-08 22:56:57
【问题描述】:

我正在尝试将图像从文档目录加载到UICollectionView。它的工作原理:流畅,快速....(笑)。但是我遇到了一个问题:当我打电话给[collectionView reloadData] 时,图像会闪烁(一次)。这是我的代码:

- (UICollectionViewCell*)collectionView:(UICollectionView *)collectionView_ cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    NSString *cellIdentifier = NSStringFromClass([AFMyRecentCollectionViewCell class]);
    AFMyRecentCollectionViewCell *cell = (AFMyRecentCollectionViewCell*)[collectionView_ dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
    AFMyRecentObject *recent = [[AFRecentManager sharedInstance].arrayRecent objectAtIndex:indexPath.row];

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
    dispatch_async(queue, ^{
        UIImage *image;
        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSString *filePath = [self databasePathWithPathComponent:[NSString stringWithFormat:@"%@.jpg", recent.id_film]];
        if ([fileManager fileExistsAtPath:filePath] == YES) {
            image = [UIImage imageWithContentsOfFile:filePath];
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            if (image) {
                cell.imageView.image = image;
            } else {
                cell.imageView.image = [UIImage imageNamed:@"loadding.png"];
            }
        });
    });

    cell.layer.shouldRasterize = YES;
    cell.layer.rasterizationScale = [UIScreen mainScreen].scale;

    return cell;
}

- (NSString *)databasePathWithPathComponent:(NSString*)pathComponent {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex: 0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:pathComponent];
    return path;
}

【问题讨论】:

  • 顺便说一句,从技术上讲,您应该确保 cellUIImage 被实例化时还没有被另一个 NSIndexPath 重用。最有可能的是,因为您正在从本地存储中检索,所以这不太可能成为问题,但如果您要发起任何网络请求,当在蜂窝网络上快速滚动时,这会突然成为一个非常现实的问题。因此,使用上述模式时要非常小心,除非您确信在异步更新正在进行时不能重用单元格。

标签: ios objective-c image uicollectionview uicollectionviewcell


【解决方案1】:

你必须放置和默认/占位符图像来防止这种情况..

    // this prevents the flicker/blinks
    cell.imageView.image = nil; // if you dont have any image as placeholder

    //since you have 
    cell.imageView.image = [UIImage imageNamed:@"loadding.png"]; // this i assume your placeholder image?

    dispatch_async(queue, ^{
        //your codes..
        dispatch_async(dispatch_get_main_queue(), ^{
            // your codes..
        });
    });

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,即闪烁图像并使用以下方法解决了它。

    应用相同的延迟加载概念。就像在显示之前创建一个字典对象来存储所有图像一样,在从文档目录获取图像之前检查图像是否存在于字典中,如果它在那里,然后使用该图像来显示它。

    如果字典中没有图像,则进行数据库操作。

    希望这能解决您的问题。

    【讨论】:

    • 如果你使用这种技术,我会推荐 (a) NSCache 而不是字典; (b) 确保在收到内存警告时清除此数据结构。另请注意,这并没有触及问题的根源,即在启动异步调用之前未能初始化 image 属性。
    • @Rob:我还没用过 NSCache。我会尝试使用它。感谢您的支持。
    【解决方案3】:

    问题是您正在启动图像视图的异步更新,但如果单元格被重用,您将在那里看到旧图像。因此,在您dispatch_async 检索图像的过程之前,请确保首先将cell.imageView.image 设置为nil。因此,在启动正确图像的异步检索之前,请确保您从未在单元格中看到先前的图像。

    【讨论】:

      猜你喜欢
      • 2015-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-31
      • 2012-09-04
      • 2012-01-27
      • 2012-04-04
      • 2010-11-04
      相关资源
      最近更新 更多