【问题标题】:How to load large amount of images in iOS?如何在 iOS 中加载大量图像?
【发布时间】:2015-04-22 23:24:38
【问题描述】:

我正在开发一个显示大量图像的应用程序。当我加载图像时,当图像超过 1000 张时加载 1000 张图像没有问题,应用程序崩溃并引发内存问题。如何解决? 有没有什么办法。请帮帮我?

提前致谢

【问题讨论】:

  • 在不知道更多信息的情况下,我会假设您的内存不足并且系统正在杀死您的应用程序。如果您有 1000 张照片,则需要缓存并正确发布它们。如果出现内存警告,只需清除所有缓存的图像以防止您的应用崩溃。

标签: ios image


【解决方案1】:

您的应用因消耗过多内存而崩溃。因此,您需要一种策略来管理您的应用使用的内存。

您需要设置一个池式系统,在该系统中您只加载那些可能“很快”显示的图像。

例如,如果用户正在查看图像 500,您可以将 498、499、501 和 502 加载到内存中。

如果他们移动到图像 501,那么您将释放 498,然后加载 503。

什么构成“很快”取决于您的应用程序的流程是如何工作的,但您应该能够想出一些可行的东西。

【讨论】:

  • 好的简短答案
  • 任何分配和解除分配图像的示例代码?对未来的读者真的很有帮助..
  • 该问题未指定引擎或框架。此外,有很多方法可以通过代码来处理问题。在这种情况下,概念性的答案很好。如果他不知道如何实际分配和取消分配图像,他可以查一下(谷歌上有大量参考资料),或者问另一个 SO 问题。
【解决方案2】:

你需要想出一个类似tableview的系统。

如果您查看它们,所有单元格都不会同时加载;如果您使用 tableview 加载您的应用程序,然后在 cellforrow 中放置一个断点,您可以体验到这一点,当您开始滚动时,您会看到它被调用。

因为不是一次加载所有单元格。

您的图像需要类似的逻辑;你不应该一次加载所有这些。如果您有理由这样做,那么我强烈建议您加载它们的缩略图版本(例如,它们的质量非常低的版本,用于所有图片的网格状视图)。

要实现这一点,您需要知道哪些图片需要立即可见,哪些图片可能很快就会可见。对于小数字,假设您总共有 10 张图片(而不是 1000 张)。

用户正在加载应用程序,并且可以在屏幕上看到图片 1 和 2。您显然会立即加载它们,以及图片 3 和最有可能的图片 4(只是为了确保)。当他滚动时,您知道他正在滚动并且您需要一种读取该滚动以动态分配正确图片的方法。您将首先释放图片 1(因为它是第一个消失的)并开始加载图片 5。

这样,您最多只能加载 5 张图片,而不是加载 1000 张图片(显然取决于大小)。

一个非常好的例子是 9gag 应用程序,它在屏幕下方加载图片,这意味着当您阅读第一个 gag 时,下一个 gag 已经加载。看到它加载的“唯一”方法是滚动快一点或连接不佳。

对我来说,这种逻辑是加载大量数据(无论是图片还是其他任何内容)最可靠和最有效的方式。

使用缓存、数组、滚动视图和文件(实际上取决于您的应用)是一个很好的起点。

【讨论】:

    【解决方案3】:

    您可能从某些 API 获取图像日期,因为将其保存到设备中是荒谬的.. :)

    我的解决方案是使用 UITableView 或 UICollectionView 取决于您选择的设计流程,因为这些 UIComponents 将为您管理内存,也就是分配可见的一次 + 5 向下和 + 5 向上,并取消分配其他的。

    您还需要异步下载图像日期,这样您 不会阻塞主 UI - 线程。

    现在...如果我是你,我肯定会选择第三方库,例如 AFNetworking 在你的情况下,它最适合处理来自服务器的 JSON 数据,也有很好的错误处理。

    在这里,我将发布一个从服务器下载图像数据的方法。

    - (void)downloadImageAsynchronicallyByUrlString:(NSString *)url forIndexPath:(NSIndexPath *)indexPath {
        // Perofrm request
        AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc]initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
        [requestOperation setResponseSerializer:[AFImageResponseSerializer serializer]];
        [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    
            // IF SUCCSESS send dataSource SUCCSESS message
            [dataSource downloadFinished:responseObject forIndexPath:indexPath];
    
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    
            // IF FAIL send dataSource FAIL message
            [dataSource downloadFailAtIndexPath:indexPath];
        }];
    
        // Start request!!!
        [requestOperation start];
    }
    

    解释:

    如果您使用 collectionView 并且我使用协议来处理 responseObject a.k.a theImage 通过协议方法发送 responseObject 时,您每次在 tableView 或 itemForRowAtIndexPath 的 cellForRowAtIndexPath 中调用此方法。

    在您的 tableView pr collectionView 所在的 UIClass 中,只需实现您的协议方法

    - (void)downloadFinished:(UIImage *)image forIndexPath:(NSIndexPath *)indexPath {
    
        // Creating copy of cell
        _lecturerCell = (LecturersCell *)[_lecturersTableView cellForRowAtIndexPath:indexPath];
        // Set downloaded image
        [_lecturerCell setLecturerImage:image];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      • 1970-01-01
      • 2013-03-30
      • 2016-01-01
      • 2010-12-06
      相关资源
      最近更新 更多