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

标签 ios multithreading memory-leaks uiimageview uicollectionview

我在 UICollectionView 中显示大量图像(5k 图像)。这些图像是从远程服务器下载的。当我从上到下滚动 UICollectionView 5 到 6 次时,我的应用程序崩溃,并收到错误“由于内存压力而终止应用程序”。请建议解决此问题。

- (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。但单元格可以重复使用多次,因此您要向单元格添加许多 ImageView 。与所有其他 ImageView 关联的图像将占用内存。

    我认为最简单/最好的解决方案是使用单元原型(prototype),在其中添加 ImageView ,并且不要以编程方式添加 ImageView 。或者,您可以通过编程方式添加 ImageView ,但请确保不要每次都添加新的 ImageView 。

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

  2. 一个更微妙的问题是,您调用 UIImageJPEGRepresentation 我猜测是为了减少所涉及的内存。这并不像你想象的那样。是的,它会创建一个压缩的 JPEG 表示形式,但您无需对其执行任何操作。你只是将其丢弃。

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

  3. 考虑使用 SDWebImageUIImageView 类别或AFNetworking ,它会延迟加载和缓存图像。

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

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

关于ios - 滚动从远程服务器加载大量图像的 UICollectionView 时如何避免内存问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30374373/

相关文章:

java - 小文件耗尽堆空间

c - 在 C 中分配的指针上 malloc 安全吗?

ios - 水平 UISwipeGestureRecognizer 不适用于 Small UIImageView

ios - 如何获得 TableView 的正确索引

java - 使用以下逻辑生成唯一的随机数。但看起来它失败了

java - Java线程中的System.exit

android - 为什么 EditText 在 Ice Cream Sandwich 中保留其 Activity 的上下文

c# - 如何从 viewmodel 使用 iOS/Xamarin 扫描 NFC 标签

ios - 动态设置Scrollview的Contentsize不起作用

c# - 如何正确使用 ConcurrentQueue 中的 block