简体   繁体   English

如何使用更少的内存在 collectionView 中显示照片库

[英]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.

相关问题 如何在CollectionView中显示照片库或相机中的选定图像? 图库视图 - How can I display selected images from the Photo Library or Camera in a CollectionView? Gallery view 如何将纯色图像插入照片库集合视图 - How to insert solid color images into photo library collectionview 如何使用 Firebase 将新照片上传到 collectionView 单元格? - How would I upload new photo into collectionView cell using Firebase? 如何在 Xcode 中显示照片库图像? - How to display photo library image in Xcode? 如何在 Cordova 中显示照片库权限对话框? - How to display photo library permissions dialog in Cordova? 如何使用Swift将照片库的最新照片添加到uiimageview? - How to add latest photo of photo library to uiimageview using Swift? 如何将带有 imagepickercontroller 的照片作为缩略图放入 collectionView 单元格 - how to get a photo with imagepickercontroller into the collectionView cell as thumbnail 使用ALAssetsLibrary在某些设备中照片库显示为空 - Photo library display empty in some devices using ALAssetsLibrary 如何在 CollectionView 中只显示 5 个单元格? - How to display only 5 cells in CollectionView? 使用照片框架将图像保存到照片库 - Save image to photo library using photo framework
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM