2017-04-07 21 views
1

現在、カメラのロールからデータを取得してすべての動画をコレクションに読み込むUIコレクションがあります。今私がしようとしているのは、AVPlayerである私のカスタムUIViewで再生するために、コレクション内のビデオを選択するときです。私はビデオを再生するとき、それは常にビデオのURLを添付して配列で正しいビデオを再生しないことを除いて、すべてが素晴らしい作品です。通常はライブラリからランダムな動画を再生するだけで、ビデオURLを追加する場所を指し示し、「致命的な範囲外」と言ってアプリをクラッシュさせることがあります。なぜこれが起きているのか分かりません。配列の値とカウントを正しく出力しています。だから私はそれが私がビデオをどのように取得しているかと関係していると思う。私はビデオを取得していますのはここAVPlayerが正しく動作しません - swift

は次のとおりです。

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 
    } 
} 
} 

各セルのロード - >

 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かかわらず、私はこの問題を考えていない: - >>私は思います問題は

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] 
} 

0123ある場所です
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

、私はそれは私がビデオを追加して検索していますどのように関係していると思います。

答えて

0

2つの配列を持つ代わりに、小さなクラスや構造体(メディア)を作成して画像と動画を保持し、コレクションビューに使用するMedia配列を作成するほうがずっと安全だと思います。これは、フェッチの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を投入するために、メディアの配列を使用します。常にデータをアンラップすることを忘れないでください。力のアンラッピングを使わないでください。(ほとんど)クラッシュすることはありません。

+0

ありがとうございました!できます! – AndrewS

関連する問題