[英]How to display photo library in collectionView using less memory
I'm facing the problem that people are saying that the application crashes when loading photos library in collectionView.我面临的问题是,人们说在 collectionView 中加载照片库时应用程序崩溃。 Most of the time they have more than 2-3 thousands of photos.大多数时候,他们有超过 2-3 千张照片。 For me it's working fine.对我来说它工作正常。 (I have less than 1000 photos in my library). (我的图库中只有不到 1000 张照片)。
Question: maybe there's any way to display images in collectionView more "smart" and using less memory?问题:也许有什么方法可以在 collectionView 中显示更“智能”的图像并使用更少的内存?
PS Maybe when user have all of his photos in iCloud that can cause crash too? PS也许当用户在iCloud中拥有他的所有照片时也会导致崩溃? Because until now I thought that application is not downloading photos when loading it into the cell.因为直到现在我认为该应用程序在将其加载到单元格时不会下载照片。 Maybe someone can prove or disapprove that fact.也许有人可以证明或反对这一事实。
Here's my function:这是我的功能:
func grabPhotos(){
let imgManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = false
requestOptions.deliveryMode = .opportunistic // Quality of images
requestOptions.isNetworkAccessAllowed = true
requestOptions.isSynchronous = true
requestOptions.progressHandler = { (progress, error, stop, info) in
print("progress: \(progress)")
}
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
if let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions) {
if fetchResult.count > 0 {
for i in 0..<fetchResult.count {
imgManager.requestImage(for: fetchResult.object(at: i) , targetSize: CGSize(width: 150, height: 150), contentMode: .aspectFill, options: requestOptions, resultHandler: { image, error in
self.imageArray.append(image!)
self.kolekcija.reloadData()
})
}
}
else {
print("You got no photos")
kolekcija.reloadData()
}
}
}
The problem is this line: 问题是这一行:
self.imageArray.append(image!)
Never make an array of images. 切勿制作图像阵列。 Images are huge, and you'll run out of memory. 图像非常大,您将耗尽内存。
This is a collection view. 这是一个集合视图。 You simply supply the image on demand in itemForRowAt:
, and what you supply is a small version of the image (a so-called thumbnail ), the smallest possible for the display size. 您只需在itemForRowAt:
按需提供图像,然后提供的是图像的较小版本(所谓的缩略图 ),是显示尺寸的最小版本。 Thus there are, at any time, only enough thumbnails to fill the visible screen; 因此,在任何时候,只有足够的缩略图可以填充可见屏幕; that doesn't take very much memory, plus the runtime can release the image memory when an image is scrolled off the screen. 这样就不会占用太多内存,而且当图像从屏幕上滚动时,运行时还可以释放图像内存。
That is what PHCachingImageManager is for. 那就是PHCachingImageManager的目的。 Look closely at how Apple handles this in their sample code: 在示例代码中仔细查看Apple如何处理此问题:
https://developer.apple.com/library/archive/samplecode/UsingPhotosFramework/Listings/Shared_AssetGridViewController_swift.html https://developer.apple.com/library/archive/samplecode/UsingPhotosFramework/Listings/Shared_AssetGridViewController_swift.html
There is no array of images anywhere in that example. 在该示例中, 任何地方都没有图像阵列。
Working in Swift 5. Get the photo assets, but don't load the photos until cellForItem iteration.在 Swift 中工作 5. 获取照片资产,但在 cellForItem 迭代之前不要加载照片。 Happy coding.快乐编码。
var personalImages: PHFetchResult<AnyObject>!
func getPersonalPhotos() {
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
self.personalImages = (PHAsset.fetchAssets(with: .image, options: fetchOptions) as AnyObject?) as! PHFetchResult<AnyObject>?
photoLibraryCollectionView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return personalImages.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "insertCellIdentifierHere", for: indexPath) as! InsertACollectionViewCellHere
let asset: PHAsset = self.personalImages[indexPath.item] as! PHAsset
let itemWidth = photoLibraryCollectionView.frame.size.width / 2
let itemSize = CGSize(width: itemWidth, height: itemWidth / 2) // adjust to your preferences
PHImageManager.default().requestImage(for: asset, targetSize: itemSize, contentMode: .aspectFill, options: nil, resultHandler: {(result, info)in
if result != nil {
cell.photoImageView.image = result
}
})
cell.layoutIfNeeded()
cell.updateConstraintsIfNeeded()
return cell
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.