2017-01-23 3 views
0

Я использую PHCachingImageManager().requestAVAsset загрузить некоторые видео с камеры ролл:.Сбой при использовании 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 линии и показывает:

НИТИ 1: EXC_BREAKPOINT

(выделены зеленым цветом)

Я не уверен, что происходит и не могу найти что-либо, что я понимаю в документации. Как это исправить?

+0

У вас есть две операции принудительного разворота в одном из параметров этого вызова ('(vidLocation? [VideoSender]!)!'). Вероятно, по крайней мере один из них равен нулю. Кроме того, хотя это не связано с вашим сбоем, у вас неверное предположение - обработчик завершения для 'requestAVAsset' является асинхронным, поэтому он будет выполнять * после * код, который устанавливает ваш' playerItem', поэтому 'asset2' всегда будет равен нулю время, когда вы пытаетесь его использовать. – rickster

ответ

0

Есть несколько вещей, которые вы собираетесь сделать здесь, чтобы получить эту работу.

  1. Вам необходимо кэшировать PHCachingImageManager как свойство объекта, который останется в живых. Если вы просто создадите его, не сохранив его где-нибудь, правила ARC заставят его выбросить. В приведенном ниже коде я использую ленивый var, но это не единственный способ сделать это.
  2. Вы должны устранить все принудительно развернутые опции ! в вашем коде. Использование шаблонов guard let ... или if let ... может показаться более типичным, но это сэкономит вам много времени и разочарования в конце. Подумайте о ! в качестве знака опасности, который гласит: «КРАСНО ЗДЕСЬ!».
  3. Вам необходимо установить AVPlayerItem из блока завершения resultHandler. requestAVAsset является асинхронным, так что он не блокирует ваш основной поток, в то время как он делает потенциально дорогостоящую работу по извлечению вашего актива. В принципе, как только вы вызываете 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 phassset = vidLocation? [VideoSender] else {return // Нет видео}' Мне пришлось изменить его на это: 'guard let phassset = vidLocation? [VideoSender] else { return} // Нет видео 'Останавливается закрывающая скобка else. – ZiEiTiA

+0

Ах, конечно. Я обновлю ответ на матч. –