崩潰

2017-01-23 228 views
0

我使用PHCachingImageManager().requestAVAsset加載從相機膠捲一些視頻:崩潰

override func viewDidLoad() { 
    super.viewDidLoad() 
    print("SEGUE SUCCESSFUL") 
    view.backgroundColor = .black 
    avPlayerLayer = AVPlayerLayer(player: avPlayer) 
    view.layer.insertSublayer(avPlayerLayer, at: 0) 

    var asset2:AVAsset? = nil 

    PHCachingImageManager().requestAVAsset(forVideo: (vidLocation?[videoSender]!)!, options: nil, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) in 
     asset2 = asset! as AVAsset 
     }) 


    let playerItem = AVPlayerItem(asset: asset2!) 
    avPlayer.replaceCurrentItem(with: playerItem) 
} 

然而,當我運行它會暫停在PHCachingImageManager().requestAVAsset線和顯示程序:

THREAD 1:EXC_BREAKPOINT

(以綠色突出顯示)

我不確定發生了什麼,也找不到我在文檔中理解的任何內容。我該如何解決?

+0

您在該調用的一個參數('(vidLocation?[videoSender]!)!')中有兩個強制展開操作。可能至少有一個是零。另外,雖然它與你的崩潰無關,但你有一個不正確的假設 - requestAVAsset的完成處理程序是異步的,所以它會在設置你的'playerItem'的代碼之後執行*,所以'asset2'將始終爲零你嘗試使用它的時間。 – rickster

回答

0

爲了實現這個目標,你需要在這裏做幾件事情。

  1. 您需要將PHCachingImageManager緩存爲保持活動狀態的對象的屬性。如果您只是在不存儲它的地方創建它,ARC規則將導致它被丟棄。在下面的代碼中,我使用了一個懶惰的var,但這不是唯一的方法。
  2. 您應該刪除代碼中的所有強制解包選項!。使用guard let ...if let ...模式可能會感覺更像打字,但最終會爲您節省大量時間和挫敗感。把!想象成一個危險信號,說「在這裏碰到!」。
  3. 您需要設置resultHandler完成塊中的AVPlayerItemrequestAVAsset是異步的,因此它不會阻塞您的主線程,但它會執行檢索資源的昂貴工作。基本上,只要您致電requestAVAsset,一個單獨的線程就會運行,並且主線程繼續處理viewDidLoad方法中的其餘代碼。當它成功檢索到AVAsset時,它會回調您最初提供的代碼塊(在主線程上),以便繼續處理。

這裏是你的代碼重寫,包括我的建議的更改:

lazy var imageManager = { 
    return PHCachingImageManager() 
}() 

override func viewDidLoad() { 
    super.viewDidLoad() 
    print("SEGUE SUCCESSFUL") 
    view.backgroundColor = .black 
    avPlayerLayer = AVPlayerLayer(player: avPlayer) 
    view.layer.insertSublayer(avPlayerLayer, at: 0) 

    var asset2:AVAsset? = nil 
guard let phAsset = vidLocation?[videoSender] else { return } //No video 

imageManager.requestAVAsset(forVideo: phAsset, options: nil, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) in 
    if let avAsset = asset { 
     self.play(asset: avAsset) 
    } 
}) 

func play(asset: AVAsset) { 
    let playerItem = AVPlayerItem(asset: asset) 
    avPlayer.replaceCurrentItem(with: playerItem) 
} 

讓我知道如果有不清楚的地方。

+1

完美 - 這完成了工作。唯一對代碼的編輯是在這一行:'guard let phAsset = vidLocation?[videoSender] else {return // No video}'我必須改變它爲:'guard let phAsset = vidLocation?[videoSender] else { return} //無視頻else else的右括號被註釋掉。 – ZiEiTiA

+0

啊,當然。我會更新答案以匹配。 –