崩溃

问题描述:

我使用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

为了实现这个目标,你需要在这里做几件事情。

  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

啊,当然。我会更新答案以匹配。 –