AVPlayer与我的阵列无法正常工作 - 迅捷

时间:2017-04-07 14:22:00

标签: sorting swift3 uicollectionview uicollectionviewcell

我目前拥有的UI Collection可以从您的相机胶卷中检索数据,以便将所有视频加载到该集合中。现在我要做的是当你在集合中选择一个视频时,在我的自定义UIView中播放它是一个AVPlayer;一切都很好,除了当我播放视频时,它并不总是在数组中播放正确的视频我已经添加了视频网址。它通常只是从图书馆播放一个随机视频,有时会崩溃应用程序指向我附加视频网址的地方,并说#34;致命超出范围"。我似乎无法弄清楚为什么会这样。它正确地打印出数组的值以及计数;所以我认为这与我如何检索视频有关。

以下是我提取视频的地方:

 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{

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

            })
        }

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

每个细胞的加载 - &gt;我不认为这件事

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

    cell.uploadedFile.image = imageArray[indexPath.row]
    return cell
}

didSelect: - &gt;&gt;我认为这就是问题所在

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    displayView.frame = CGRect(x: self.view.frame.size.width / 2, y: self.view.frame.size.height / 2, width:self.view.frame.size.width / 1.15, height: self.view.frame.size.height / 1.3)
    displayView.center = view.center
    displayView.backgroundColor = UIColor.clear
    displayView.layer.cornerRadius = displayView.layer.frame.size.width / 10
    displayView.layer.borderColor = UIColor.black.cgColor
    displayView.layer.borderWidth = 4
    //displayView.avPlayerLayer.cornerRadius = displayView.avPlayerLayer.frame.size.width/10
    displayView.url = videoArray[indexPath.row]
}

计数

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

自定义播放器:

class VideoPlayBack: UIView {

var url: NSURL!
var avPlayer: AVPlayer!
var avPlayerLayer: AVPlayerLayer!
var cancelButton: UIButton!

// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {

    self.backgroundColor = UIColor.black

    avPlayer = AVPlayer(url: url! as URL)
    avPlayer.actionAtItemEnd = AVPlayerActionAtItemEnd.none
    avPlayerLayer = AVPlayerLayer(player: avPlayer)

    NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidReachEnd(_:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: avPlayer.currentItem)


    avPlayerLayer.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
    //avPlayerLayer.frame = self.layer.bounds
    self.layer.addSublayer(avPlayerLayer)
    avPlayer.play()


}

func playerItemDidReachEnd(_ notification: Notification) {
    let playerItem = notification.object as! AVPlayerItem
    playerItem.seek(to: kCMTimeZero)
}
}

以下是完整的集合视图类。

https://paste.ee/p/JgZSu

同样,我认为这与我追加和检索视频的方式有关。

1 个答案:

答案 0 :(得分:0)

我认为创建一个小类或结构(即Media)来保存图像和视频,并创建一个用于集合视图的Media数组,而不是拥有2个数组。这是因为2个获取方法是异步的,所以你永远不知道将分配哪个视频/图像组合的索引。此外,尝试嵌套异步调用,以便两个调用使用相同的媒体实例来保持数据一致性。

这是一个未经测试的例子:

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

var mediaArray = [Media]()

for i in 0..<fetchResult.count{
    let mediaItem = Media()
    //Used for fetch Image//
    imgManager.requestImage(for: fetchResult.object(at: i) as PHAsset , targetSize: CGSize(width: 200, height: 200), 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 = URL(string: "\(asset.url)")
                let duration : CMTime = asset.duration
                let durationInSecond = CMTimeGetSeconds(duration)
                print(durationInSecond)
                mediaItem.videoURL = videoData!
                self.mediaArray.append(mediaItem)
            }

        })
    })
} 

然后使用媒体数组填充collectionView。不要忘记始终打开数据。不要使用力展开,你(几乎)永远不会崩溃