Видео и его эскизы не сохраняются в последовательности после извлечения из фотографий

Я использую код ниже для получения видео (URL, продолжительность, миниатюры). После получения данных я отображаю их на CollectionView, Основная проблема в том, что некоторые видео и его миниатюры не соответствуют друг другу. Может кто-нибудь сказать, пожалуйста, как я могу это исправить, или любое другое лучшее решение? Спасибо

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

        cell.imgV.image = photoLibrary[indexPath.row]

        let duration: TimeInterval = videosDuration[indexPath.row] // 2 minutes, 30 seconds
        let formatter = DateComponentsFormatter()
        formatter.unitsStyle = .positional
        formatter.allowedUnits = [ .minute, .second ]
        formatter.zeroFormattingBehavior = [ .pad ]
        let formattedDuration = formatter.string(from: duration)
        cell.duration.text = "\(String(describing: formattedDuration!))"

        return cell
    }

    func grabPhotos(){
        let imgManager = PHImageManager.default()

        let requestOptions = PHImageRequestOptions()
        requestOptions.isSynchronous = false
        requestOptions.deliveryMode = .highQualityFormat

        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
        if let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions) {
            if fetchResult.count > 0 {
                for i in 0..<fetchResult.count{
                    //Used for fetch Image//
                    imgManager.requestImage(for: fetchResult.object(at: i) as PHAsset , targetSize: CGSize(width: 100, height: 100), contentMode: .aspectFill, options: requestOptions, resultHandler: {
                        image, error in
                        let imageOfVideo = image! as UIImage
                        self.photoLibrary.append(imageOfVideo)
                    })
                    //Used for fetch Video//
                    imgManager.requestAVAsset(forVideo: fetchResult.object(at: i) as PHAsset, options: PHVideoRequestOptions(), resultHandler: {(avAsset, audioMix, info) -> Void in
                        if let asset = avAsset as? AVURLAsset {
                            self.videoURL.append(asset.url)
                            let duration : CMTime = asset.duration
                            let durationInSecond = CMTimeGetSeconds(duration)
                            self.videosDuration.append(durationInSecond)
                        }
                    })
                }
            }
            else{
                //showAllertToImportImage()//A function to show alert
            }
        }

    }

1 ответ

Решение

Поскольку фотографии выбираются асинхронно, поэтому в массиве изображений и видео порядок не поддерживается, поэтому для получения соответствующего изображения для видео можно использовать словари для сохранения результата.

Я сделал некоторые изменения в вашем коде, пожалуйста, проверьте

var imageDictionary = [String: AnyObject]()
var videoDictionary = [String: AnyObject]()

func fetchData(){
        let imgManager = PHImageManager.default()

        let requestOptions = PHImageRequestOptions()
        requestOptions.isSynchronous = false
        requestOptions.deliveryMode = .highQualityFormat

        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
        if let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions) {
            if fetchResult.count > 0 {
                for i in 0..<fetchResult.count{
                    //Used for fetch Image//

                    imgManager.requestImage(for: fetchResult.object(at: i) as PHAsset , targetSize: CGSize(width: 100, height: 100), contentMode: .aspectFill, options: requestOptions, resultHandler: {
                        image, error in
                        let imageOfVideo = image! as UIImage
                        //self.photoLibrary.append(imageOfVideo)
                        let key = "\(i)"
                        self.imageDictionary[key] = imageOfVideo
                    })
                    //Used for fetch Video//
                    imgManager.requestAVAsset(forVideo: fetchResult.object(at: i) as PHAsset, options: PHVideoRequestOptions(), resultHandler: {(avAsset, audioMix, info) -> Void in
                        if let asset = avAsset as? AVURLAsset {
                            //let videoData = NSData(contentsOf: asset.url)
                            self.videoURL.append(asset.url)
                            //print(asset.url)
                            let duration : CMTime = asset.duration
                            let durationInSecond = CMTimeGetSeconds(duration)
                            //self.videosDuration.append(durationInSecond)
                            //print(durationInSecond)
                            let key = "\(i)"
                            self.videoDictionary[key] = ["VideoURL" : asset.url, "VideoDuration" : durationInSecond]
                        }
                    })
                }
            }
            else{
                //showAllertToImportImage()//A function to show alert
            }
        }

    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.imageDictionary.count
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

               //You can access the values like this....

               let key = "\(indexPath.row)"

               cell.image = self.imageDictionary[key] as? UIImage
               let singleVideo = self.videoDictionary[key] as? [String: AnyObject]

               cell.videoURL = singleVideo["VideoURL"] as? URL
               cell.videoDuration = singleVideo["VideoDuration"] as? CMTime


    }
Другие вопросы по тегам