【问题标题】:Vast memory required with UICollectionView images set from NSDictionary从 NSDictionary 设置的 UICollectionView 图像需要大量内存
【发布时间】:2014-08-06 21:00:02
【问题描述】:

我正在制作一个应用程序,其中包含来自数据库的大量条目,显示在 UICollectionView 中,并且集合视图中的每个项目都显示一个图像。但是,有很多重复的图像(即,我的UICollectionView 有 200 个项目但只有大约 30 个可能的图像)。

最初我通过在我的cellForItemAtIndexPath 方法中调用cell.imageview.image =[UIImage imageWithContentsOfFile] 来分配这些图像,但这会导致滚动延迟,可能是由于每次都必须从内部存储器中读取图像。

现在我想通过创建一个数组/字典并在每次调用 cellForItem 时引用它来完成 viewDidLoad 中的所有 I/O。当我这样做并在 viewDidLoad 中创建UIImages 的字典并拥有cell.imageview.image = [imageDictionary objectForKey:] 时,它会正确显示图像并且滚动非常流畅,但是使用的内存很大(它只会增加直到它一直滚动到底部,所以我认为它在 RAM 中有所有 200 个图像实例)。

但是,如果我使用图像的NSData 填充viewDidLoad 中的字典并使用cell.imageView = [UIImage imageWithData:[dataDictionary objectForKey:]] 设置图像,则使用的内存效率要高得多,并且仅反映屏幕上当前显示的内容。但是,滚动再次变得略微滞后。

我的问题是:为什么只有当我用 UIImages 而不是 NSData 填充字典时才会发生内存泄漏? iOS 会不会意外自动缓存图片之类的?

希望这是有道理的 - 如果不深入了解我的代码细节,很难说清楚。

【问题讨论】:

  • 如果你只有 30 张可能的图片,你为什么要加载所有的副本?重复项是否易于识别(通过文件名或类似名称)?
  • 是的,数据源为每个项目指定了必要的图像文件名。我不确定我是否理解您的问题 - 我加载重复图像的唯一时间是在 cellForItem 内,我必须在那里做吗?也许我遗漏了一些明显的东西,抱歉!
  • 当您在 viewDidLoad 中创建图像字典时,该字典中有 200 个图像还是 30 个图像,您是如何创建这些图像的?
  • 啊,我明白了——它有 30 张图像——对象是 UIImage,键是每个 UIImage 的文件路径。我通过调用imageWithContentsOfFile 在字典中创建每个图像。
  • 那么字典只有 30 个键,还是说它只有 30 个不同的图像,但有 200 个键?

标签: ios objective-c memory uiimage


【解决方案1】:

使用您的第一种方法在滚动时设置图像。但是,在后台线程中加载图像,然后在主线程上设置图像,这样您就不会抑制滚动。此外,请确保您的图像与图像视图的大小相同(即不是很大),这样它们就不会占用大量内存。

例子:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {

    UIImage *image = [UIImage imageWithContentsOfFile... // do stuff

    dispatch_async(dispatch_get_main_queue(), ^(void) {

        [[cell imageView] setImage:image];

    });

});

【讨论】:

  • 非常感谢 - 我实际上已经这样做了,发现它工作得很好,但仍然不如我描述的导致内存问题的方法那么好,所以我想知道是否有一种使它起作用的方法:)
  • 预加载图像总是对性能有好处,但对内存没有好处。也许在内存中缓存下两行和前两行并在表格滚动时相应地加载其余行?
猜你喜欢
  • 2014-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-13
  • 2016-08-21
相关资源
最近更新 更多