滚动从远程服务器加载大量图像的 UICollectionView 时如何避免内存问题?

How to avoid the memory issue while scrolling an UICollectionView which loads lot of images from Remote server?

我在 UICollectionView 中显示了很多图像(5000 张图像)。这些图像已从远程服务器下载。当我从 UICollectionView 的顶部滚动到底部,反之亦然 5 到 6 次时,我的应用程序崩溃并收到错误 "Terminating app due to memory pressure"。请建议解决此问题。

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return urlLists.count;
}


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
   UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];
    UIImageView *cellImage=[[UIImageView alloc]init];
    cellImage.frame=cell.contentView.bounds;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[urlLists objectAtIndex:indexPath.row]]];
        UIImage *image = [UIImage imageWithData:data];
        UIImageJPEGRepresentation(image, 0.1);
                data=nil;
         dispatch_async(dispatch_get_main_queue(), ^{
            cellImage.image=image;
        });
    });

    NSLog(@"The Indexpath=%ld", indexPath.row);
    [cell.contentView addSubview:cellImage];

    return cell;

}

您是否尝试过分析应用并查看其泄漏的确切位置?

这里的问题分为三级:

  1. 最严重的问题是每次使用该单元格时都会向该单元格添加一个新的 UIImageView。但是单元格可以重复使用很多次,因此您要向单元格添加许多图像视图。与所有其他图像视图关联的图像将占用内存。

    我认为 easiest/best 解决方案是使用单元格原型,在那里添加图像视图,并且不要以编程方式添加图像视图。或者,您可以通过编程方式添加图像视图,但请确保您不会每次都添加新的图像视图。

    顺便说一句,不要每次都手动实例化一个新单元来关闭单元重用(正如这里其他人可能会建议的那样)。是的,这是一个简单的解决方案,但效率不高。

  2. 一个更微妙的问题是您调用 UIImageJPEGRepresentation 我猜是为了减少所涉及的内存。那并不像您认为的那样。是的,它创建了一个压缩的 JPEG 表示,但您不对其进行任何操作。你只是在丢弃它。

    如果您想优化内存并且图像是高分辨率的,请考虑将图像调整为适合单元格的大小。有关调整类别大小的示例,请参阅 UIImage resizing not working properly

  3. 考虑使用 SDWebImage or AFNetworkingUIImageView 类别,它可以延迟加载和缓存图像。

    问题中的这段代码在启动异步检索之前不会正确重置图像视图。如果在图像检索完成之前重复使用单元格,它将不会处理这种情况。它可能会不必要地重新检索几秒钟前下载的图像。等等

    有很多与优雅地异步检索图像相关的问题,这两个 类 的 UIImageView 类别为您处理了很多这些细节。