我的ViewController看起来像:顶部的摄像头视图和底部的照片库,就像在Instagram中一样。
当我尝试加载用户的图像库并在UICollectionView上显示时,应用程序崩溃了Memory Warning
。如何防止它并改善我的功能?
我的功能:
func getImagesFromLibrary(from: Int = 0, to: Int = 5, completion: (loaded: Bool) -> Void) {
if images.count > 0 {
for i in from..<to {
let asset: PHAsset = self.images[i] as! PHAsset
let imageFetchOptions = PHImageRequestOptions()
self.imageManager.requestImageForAsset(asset, targetSize: CGSize(width: 75, height: 75), contentMode: .AspectFit, options: imageFetchOptions, resultHandler: { (image: UIImage?, info: [NSObject : AnyObject]?) in
if (image != nil) {
if let img = image {
self.croppedImagesArray[i] = img
self.imagesCollectionView.reloadData()
}
}
})
}
completion(loaded: true)
} else {
print("Images Empty")
}
}
我通过以下方式致电:
if AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) == AVAuthorizationStatus.Authorized {
print("GRANTED")
self.getImagesFromLibrary { (loaded) in
if loaded {
print("Images Count: \(self.images.count)")
if self.images.count > 5 {
print("Second part")
self.getImagesFromLibrary(5, to: self.images.count / 2, completion: { (loaded) in
if loaded {
self.getImagesFromLibrary(self.images.count / 2, to: self.images.count, completion: { (loaded) in })
}
})
}
}
}
}
所以,现在我在我的画廊中有300张图片。这很重要,这就是我的应用程序在加载过程中崩溃的原因。
我该如何解决?任何解决方案?
答案 0 :(得分:0)
显然,您只是在内存中保留了太多图像,因此会收到内存警告 当您收到内存警告时,iOS会让您有机会发布易于重新创建的数据。如果您不这样做,您的应用程序可以随时终止。
所以问题是你是否真的需要将所有这些图像保存在记忆中 如果是这样,您就会遇到真正的问题,iOS可能不适合您的应用平台 如果没有,例如如果您想一次只显示部分加载的图像,则应使用在应显示的图像不在内存中时显示的占位符图像,下载图像,并尽快用实际图像替换占位符它已被下载。
存储图片以便不会收到内存警告的一种方法是使用NSCache
&lt; Docs&gt ;,这类似于NSMutableDictionary
,其中您可以存储图像,但是当内存变紧时,将会自动清除未长时间使用的图像。因此,如果您必须显示图像,则可以先显示占位符,然后尝试从缓存中加载它,如果失败,则下载它。
当然,还有一些框架可以自动为您进行缓存,例如AFNetworking
&lt; Github&gt;。
答案 1 :(得分:0)
默认情况下,requestImageForAsset:是异步的。您编写的代码将立即触发对所有300个图像的请求,并且您看到内存不足。所以加载5个图像的代码,然后是前半部分,然后是后半部分,只是一次运行。
我建议在UICollection cellForRowAtIndexPath中:你调用self.imageManager.requestImageForAsset(self.images [indexPath.item] ....并在结果处理程序块中为该单元格设置UImageView。无需预加载所有300张图像,用户可能永远不会滚动查看全部。而其他人可能有3000张或更多图像。
同样在结果处理程序中,每次获取图像时都调用collectionView reloadData,甚至在当前甚至不显示所获取的图像时重新加载。使用reloadItemsAtIndexPath:只加载与图像关联的单元格。