【发布时间】:2015-10-25 10:53:27
【问题描述】:
在我的 iOS 应用程序中,我有 UICollectionView,它显示了大约 1200 个小(35x35 点)图像。图像存储在应用程序包中。
我正确地重用了UICollectionViewCells,但仍然存在性能问题,具体取决于我处理图像加载的方式:
我的应用程序是应用程序扩展,内存有限(本例中为 40 MB)。将所有 1200 张图像放入资产目录并使用
UIImage(named: "imageName")加载它们导致内存崩溃 - 系统缓存的图像填满了内存。在某些时候,应用程序需要分配更大的内存,但由于缓存的图像,这些内存不可用。操作系统没有触发内存警告和清理缓存,而是直接杀死了应用程序。我更改了方法以避免图像缓存。我将图像作为 png 文件放入我的项目(而不是资产目录),我现在使用
NSBundle.mainBundle().pathForResource("imageName", ofType: "png")加载它们。该应用程序不再因内存错误而崩溃,但加载单个图像需要更长的时间,即使在最新的 iPhone 上,快速滚动也会滞后。
我可以完全控制图像,并且可以将它们转换为 .jpeg 或优化它们(我已经尝试过 ImageOptim 和其他一些选项但没有成功)。
如何同时解决这两个性能问题?
编辑 1:
我还尝试在后台线程中加载图像。这是我的 UICollectionViewCell 子类中的代码:
private func loadImageNamed(name: String) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { [weak self] () in
let image = bundle.pathForResource(name, ofType: "png")?.CGImage
if name == self?.displayedImageName {
dispatch_async(dispatch_get_main_queue(), {
if name == self?.displayedImageName {
self?.contentView.layer.contents = image
}
})
}
})
}
这使得滚动平滑而不消耗额外的缓存内存但是当以编程方式滚动到某个位置时(例如当UICollectionView滚动到顶部时)它会导致另一个问题:在滚动动画期间,图像不会更新(滚动速度太快,无法加载),滚动完成后,会在几分之一秒内显示错误的图像 - 并且一个接一个地替换为正确的图像。这在视觉上非常令人不安。
编辑 2:
我无法将小图像组合成更大的组合图像并按照this answer 的建议显示这些图像。
原因:
- 考虑不同的屏幕尺寸和方向。它们中的每一个都必须有预先合成的图像,这会使应用程序下载量很大。
- 小图像可以以不同的顺序显示,其中一些可能在某些情况下被隐藏。我肯定无法为每种可能的组合和顺序预先组合图像。
【问题讨论】:
-
您需要某种缓存,可以根据需要从您的标准图像中填充,然后在启动并运行后快速访问,以便滚动等顺畅。以下链接似乎提供了这种机制。看起来它使用内存映射文件并避免了很多开销。可能值得一看? github.com/path/FastImageCache
标签: ios image performance memory uicollectionview