我正在努力解决从iPhone显示相册到collectionView的问题。

如果某人在画廊内有50张照片,那么一切都会正常进行。问题是,当某人有数千张照片时,图库会加载10秒钟,这对我的应用程序不利。当我从Facebook加载图像时,会发生相同的问题。该应用程序正在等待,直到它下载了每张照片,然后显示出来。我想在加载过程中一张一张显示图像,而不是等待它全部加载。

我知道我应该使用DispachQueue,但确实做到了,但是有一些我看不到的错误。
这是我用来从iPhone图库中获取图像的代码:

func grapPhotos() {
    let imgManager = PHImageManager.default()
    let requestOptions = PHImageRequestOptions()
    requestOptions.isSynchronous = true
    requestOptions.deliveryMode = .highQualityFormat
    let fetchOptions = PHFetchOptions()

    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]

    if let fetchResulat : PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions) {

        if fetchResulat.count > 0 {

            for i in 0..<fetchResulat.count {

                imgManager.requestImage(for: fetchResulat.object(at: i), targetSize: CGSize(width: 200, height:200), contentMode: PHImageContentMode.aspectFill, options: requestOptions, resultHandler: {
                    (image, eror) in

                    self.imageArray.append(image!)

                    DispatchQueue.main.async {
                        self.collectionView.reloadData()
                    }
                })
            }
        } else {

            print("You have no photos")
            self.collectionView.reloadData()
        }
    }
}

并在collectionView中显示它们的代码:
 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return imageArray.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "galleryCell", for: indexPath) as! GalleryCollectionViewCell

        let image = self.imageArray[indexPath.row]

        DispatchQueue.main.async {
            cell.gelleryImages.image = image
            }

    return cell
}

我的Facebook类(class)可能存在相同的问题,因此,我将非常感谢您的帮助。

最佳答案

您需要将fetchResult属性添加到集合 View Controller ,并在viewDidLoad方法中获取图像Assets。

var fetchResult: PHFetchResult<PHAsset> = PHFetchResult()

func fetchAssets() {
    let fetchOptions = PHFetchOptions()
    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
    fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
}

override func viewDidLoad() {
    super.viewDidLoad()
    fetchAssets()
}
下一步是扩展UIImageView,以请求图像数据在完成时异步设置其图像。
extension UIImageView {
    func fetchImage(asset: PHAsset, contentMode: PHImageContentMode, targetSize: CGSize, version:  PHImageRequestOptionsVersion = .current, deliveryMode: PHImageRequestOptionsDeliveryMode = .opportunistic) {
        let options = PHImageRequestOptions()
        options.version = version
        options.deliveryMode = deliveryMode
        PHImageManager.default().requestImage(for: asset, targetSize: targetSize, contentMode: contentMode, options: options) { image, _ in
            guard let image = image else { return }
            switch contentMode {
            case .aspectFill: self.contentMode = .scaleAspectFill
            case .aspectFit:  self.contentMode = .scaleAspectFit
            @unknown default: fatalError()
            }
            self.image = image
        }
    }
}
现在,您可以一次在集合 View cellForItemAt方法中获取一张图像:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! CollectionViewCell
    let asset = fetchResult.object(at: indexPath.row)
    cell.imageView.fetchImage(asset: asset, contentMode: .aspectFill, targetSize: cell.imageView.frame.size * UIScreen.main.scale )
    return cell
}
不要忘记为numberOfItemsInSection方法返回fetchResult计数。
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return fetchResult.count
}
class CollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var imageView: UIImageView!
}
extension CGSize {
    static func *(lhs: CGSize, rhs: CGFloat) -> CGSize {
        .init(width: lhs.width * rhs, height: lhs.height * rhs)
    }
}

10-06 04:28