arrays - UICollectionView 没有显示我的所有数组

标签 arrays swift swift3 uicollectionview uicollectionviewcell

我目前有一个自定义 UICollection,它从用户的相机胶卷加载用户视频库。现在我现在可以将所有视频添加到一个数组中;并打印出正确的视频数量;但是我的 UICollection 没有显示我库中的所有视频(共 119 个)。任何人都知道为什么会发生这种情况?

这是我的代码:

struct Media {
        var image:UIImage?
        var videoURL:NSURL?
    }

    var mediaArray = [Media]()


    func grabPhotos(){
        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 fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions) {


            if fetchResult.count > 0 {
                for i in 0..<fetchResult.count{
                    var mediaItem = Media()
                    //Used for fetch Image//
                    imgManager.requestImage(for: fetchResult.object(at: i) as PHAsset , targetSize: CGSize(width: 400, height: 400), contentMode: .aspectFit, options: requestOptions, resultHandler: {
                        image, error in
                        let imageOfVideo = image! as UIImage
                        mediaItem.image = 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 = NSURL(string: "\(asset.url)")
                                let duration : CMTime = asset.duration
                                let durationInSecond = CMTimeGetSeconds(duration)
                                print(durationInSecond)
                                mediaItem.videoURL = videoData!
                                self.mediaArray.append(mediaItem)
                                print(self.mediaArray.count)

                            }

                        })
                    })
                }

            }
            else{
                //showAllertToImportImage()//A function to show alert
            }
        }
    }

还有我的 cellForItemAt

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

        cell.uploadedFile.image = mediaArray[indexPath.row].image 


        return cell
    }

& 在我的 viewWillAppear 中,我创建了 UICollection:

let flowLayout = UICollectionViewFlowLayout()


        let collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: flowLayout)
        collectionView.register(VideoSelectionCVCell.self, forCellWithReuseIdentifier: cellId)

        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.backgroundColor = UIColor.clear

        self.view.addSubview(collectionView)

我认为正在发生的事情是在 grabPhotos() 发生之前加载屏幕;并且 grabPhotos() 直到屏幕加载后才完成。我还在 viewWillAppear 中创建了我的 UICollection,因此这将使它成为私有(private)事件(如果我是正确的)。所以我想要解决这个问题,我需要公开 UICollectionView,但是如果我以编程方式执行此操作 + 在我的 View 中创建它,我会怎么做?

最佳答案

我认为有几种不同的方法可以解决这个问题。

将您的远程图像加载到 cellforitemat 中

  1. 在 Viewdidload 中添加您的 Collection View ,然后在函数调用 grabphotos 的末尾添加。
  2. 在您的 grabphotos 函数中,在获得 fetchResult 后调用 collectionView.reloadData()。
  3. 将 imgManager.requestImage 移动到 cellforitem 中。这样,您只在渲染单元格时加载每个图像。在更新 collectionView 之前,用户不会等待所有图像加载。如果您担心性能,可以添加预取。

使用 DispatchGroup

如果您真的很想在更新 collectionView 之前加载所有图像,您可以创建一个 DispatchGroup 来跟踪图像下载,然后在完成后更新 collectionView。

struct Media {
    var image:UIImage?
    var videoURL:NSURL?
}

var mediaArray = [Media]()
let loadContentGroup = DispatchGroup()

func grabPhotos(){
    loadContentGroup.notify(queue: DispatchQueue.main) { [weak self] in                     
        guard let `self` = self else { return }
        self.collectionView.reloadData()
    }

    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 fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions) {


        if fetchResult.count > 0 {
            for i in 0..<fetchResult.count{
                var mediaItem = Media()

                loadContentGroup.enter()

                //Used for fetch Image//
                imgManager.requestImage(for: fetchResult.object(at: i) as PHAsset , targetSize: CGSize(width: 400, height: 400), contentMode: .aspectFit, options: requestOptions, resultHandler: {
                    image, error in
                    let imageOfVideo = image! as UIImage
                    mediaItem.image = 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 = NSURL(string: "\(asset.url)")
                            let duration : CMTime = asset.duration
                            let durationInSecond = CMTimeGetSeconds(duration)
                            print(durationInSecond)
                            mediaItem.videoURL = videoData!
                            self.mediaArray.append(mediaItem)
                            print(self.mediaArray.count)

                            self.loadContentGroup.leave()
                        }

                    })
                })
            }

        }
        else{
            //showAllertToImportImage()//A function to show alert
        }
    }
}

关于arrays - UICollectionView 没有显示我的所有数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43750020/

相关文章:

ios - Swift:无法使用 'filter' 类型的参数列表调用 '((AnyObject) throws -> Bool)'

ios - 从烦人格式的字典中提取值

arrays - 如何将子数组添加到自身? ruby

java - 我的 Volley 应用程序崩溃了,可能是在 listView 代码上

c++ - C++中的 "for each"循环如何知道数组的长度

swift - 如何创建一个包含 `Array<Int>` 或 `UnsafePointer<UInt8>` 的类型

iOS 14 菜单选择器样式的标签在更改时有时会变暗

ios - 收到类似 malloc_error_break 的错误

swift - 具有调整单元格动画大小的动态单元格大小

ios - swift : get all installed application and open specific one