使用PHCachingImageManager()时崩溃.requestAVAsset

时间:2017-01-23 17:42:14

标签: swift swift3 avfoundation ios10 photosframework

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

(以绿色突出显示)

我不确定发生了什么,也找不到我在文档中理解的任何内容。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

为了实现这一目标,您需要做一些事情。

  1. 您需要将PHCachingImageManager缓存为将保持活动的对象的属性。如果您只是创建它而不将其存储在某个地方,ARC规则将导致它被丢弃。在下面的代码中,我使用了一个懒惰的var,但这不是唯一的方法。
  2. 您应该删除代码中所有强制解包的选项!。使用guard let ...if let ...模式可能会感觉更像打字,但它最终会为您节省大量时间和挫折。将!视为危险信号,表示“ CRASH HERE!”。
  3. 您需要设置AVPlayerItem完成块中的resultHandlerrequestAVAsset是异步的,因此它不会阻止您的主线程,同时它可能会执行检索资产的昂贵工作。基本上,只要你调用requestAVAsset一个单独的线程就可以为你工作,而主线程继续处理viewDidLoad方法中的其余代码。成功检索AVAsset后,它会回调您最初提供的代码块(在主线程上),以便继续处理。
  4. 这是你的代码被重写以包含我建议的更改:

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

    如果有什么不清楚,请告诉我。