Swift - UICollectionView或UIImage - 如何防止图片缓存

5

我有一个UICollectionView,它以4个格子的形式呈现,没有scrolling。每个格子都有一个单独的imageView。这些images存储在资源文件夹中,并通过名称引用进行检索(见下文)。在某些UI操作之后,想法是

collectionView.reloadData() 

并替换每个单元格中的image

一切工作正常,但是每次重新加载后内存使用量都在不断增加。我原以为reloadData()会清除不必要的data,但这种经验让我感到困惑。发生了什么?

如果有帮助的话,我读到过某个地方使用

加载图像时可能出现问题。

UIImage(name: ...) 

缓存图片。我尝试确认这一点,但没有结果。

我的代码非常简单,所以我想知道这是否是某种内存错误/滚动目的的功能(我不想要)。

再次强调,我想停止内存积累。有什么想法吗?


你的图片存储在bundle中还是从服务器下载的? - Amit Singh
@AmitSingh - 图像存储在资产文件夹中。 - Shane
是的,这就是原因,Assets文件夹可以与缓存一起使用。 - Amit Singh
3个回答

5
我从来没有机会理解图像缓存何时被清除。
集合视图单元格被出列并重复使用。这意味着,当单元格离开屏幕后,它将被放入回收站中,如果再次需要该单元格,则从回收站中取出并放置在您的视图层次结构中(我猜这被称为Flyweight模式),基本上您正在节省实例化成本。
因此,当你处理图像且你的图像没有存储在内存中而只是在图像视图中时,每次显示单元格并传递新图像到图像视图时,旧图像都应该被释放。
如果您在其他地方存储对旧图像的引用,例如cache或数组,则可能不会发生这种情况。
要从xcasset加载图像,您只能使用UIImage(name:...),这意味着该图像将被缓存。即使苹果说这个缓存会在内存压力情况下被清除,但我从未看到过这种情况发生,以避免应用程序崩溃。
您可以做的是不要保存在xcasset文件夹中,而是保存在您项目的任何位置,在这种方式中,它们将被加载到您的主bundle中,您可以使用常见的方式从这里加载图像:
let path = NSBundle.mainBundle().pathForResource(<#T##name: String?##String?#>, ofType: <#T##String?#>)
    let image = UIImage(contentsOfFile: path!)

请注意,路径是可选的。
通常情况下,尽量节省资源,使用像素大小相同的图像,图像占用的空间并不重要,只是它被压缩后的大小,在内存中加载时,需要 n_pixel_height * n_pixel_width * n_channels 字节。


谢谢你的答复。我不知道如何将我的图片保存在其他地方,但这似乎是一个非常好的答案。与此同时,我想我会接受缓存了。 - Shane
1
只是一个更新,我已经跟随应用程序运行时的内存缓存,一旦收到内存警告,缓存就会被清除。再次感谢您的解释。 - Shane

-1

你做得很正确,如果你使用dequeueReusableCellWithReuseIdentifier(identifier:, forIndexPath:)方法来重用单元格,那么它肯定会处理单元格的可重用性。

你没有其他方式从bundle中加载图片。

一些轻微的内存变化可能会反映出来,但没关系,继续前进吧。


每次重新加载时,内存使用量增加4MB,这似乎不太对。我现在会运行它并查看何时崩溃。 - Shane
内存使用似乎在650MB达到峰值,可能是当所有图像都被循环遍历时。考虑到每个图像只有约200kB,而且大约有300个图像,这仍然显得过多。 - Shane

-1
在你的子类UICollectionViewCell的prepareForReuse方法中
func prepareForReuse()
{
    super.prepareForReuse();
    cell.imageView.image = nil;
}

不幸的是,这对我没有起作用。无论如何还是谢谢。 - Shane
刚看到这个,想留个言。@Proton说的可能并不是坏主意,尽管他可能指的是cellForItemAtIndexPath或cellForRowAtIndexPath。他试图告诉你的是在异步加载图像之前将其视图清空。简而言之:就像将"空白图片"作为占位符一样。 - Happiehappie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接