2015-11-26 4 views
0

Я играю видео в своем приложении в TVos. Я использую AVPlayerViewController для воспроизведения видео. Но когда я нажимаю кнопку «Меню» на пульте Apple TV, я возвращаюсь к контроллеру просмотра, из которого я пришел сюда, но видео продолжает играть, и через 8 или 10 секунд оно освобождается. Это действительно плохая ошибка, и я застрял на ней в течение нескольких дней. Любая помощь будет высоко оценена.AVPlayerViewController не освобождается сразу

Вот мой код для контроллера вида.

import Foundation 
import UIKit 
import AVKit 


class ViewController : UIViewController { 


    var avplayerVC : AVPlayerViewController? 
    var recentlyWatchedTimer : NSTimer? 
    var lessonToWatch : Lesson? 


    override func viewDidLoad() { 
     super.viewDidLoad() 


     if let urlVideo = lessonToWatch?.lessonurl { 

      let activityIndicator = UIActivityIndicatorView(frame: CGRectMake(self.view.frame.size.width/2.0, self.view.frame.size.height/2.0, 30.0, 30.0)) 
      let asset : AVURLAsset = AVURLAsset(URL: NSURL.init(string: urlVideo)!, options: nil) 
      let keys = ["playable"]; 
      avplayerVC = AVPlayerViewController() 

      weak var weakSelf = self 

      asset.loadValuesAsynchronouslyForKeys(keys) {() -> Void in 
       dispatch_async(dispatch_get_main_queue(), {() -> Void in 
        weakSelf!.avplayerVC?.player = AVPlayer(playerItem: AVPlayerItem(asset: asset)) 
        weakSelf!.avplayerVC?.player?.seekToTime(kCMTimeZero) 


        print("Status 1: " + "\(self.avplayerVC?.player?.status.rawValue)") 
        print(self.view?.frame) 
        // doesn't work 

        weakSelf!.avplayerVC?.view.frame = self.view.frame 
        activityIndicator.stopAnimating() 
        activityIndicator.removeFromSuperview() 
        weakSelf!.view.addSubview((self.avplayerVC?.view!)!) 
        weakSelf!.avplayerVC?.player?.play() 
        weakSelf!.recentlyWatchedTimer = NSTimer.scheduledTimerWithTimeInterval(20.0, target: self, selector: "addToRecentlyWatched" , userInfo: nil, repeats: false) 
            }) 
      } 

      print("In LessonPlayViewController View Did Load") 
      self.view.addSubview(activityIndicator) 
      activityIndicator.startAnimating() 
     } 

    } 


    func addToRecentlyWatched() { 
     if let lesson = lessonToWatch { 
      DataManager.sharedInstance.addRecentlyWatch(lesson) 
     } 
     recentlyWatchedTimer?.invalidate() 
    } 

    deinit { 
     print("deinit") 
     avplayerVC?.view.removeFromSuperview() 
     avplayerVC?.player = nil 
     avplayerVC = nil 
    } 

    // MARK : AVPlayerViewControllerDelegate 


} 

ответ

0

Вы хотите использовать weakSelf во всех местах внутри блока обратного вызова async, но вы печатаете self.view.frame сразу же.

+0

Ну, это не имеет никакого значения. Изменение всего себя на weakSelf внутри асинхронного блока – Madu

+0

@Madu, какова трассировка стека при вызове deinit. И какой поток это? – rounak

0

Вы должны использовать список захвата, чтобы убедиться, что все ссылки на self: weak в закрытии. Затем используйте guard, чтобы проверить, что ссылки все еще действительны в пределах закрытия.

import Foundation 
import UIKit 
import AVKit 
import AVFoundation 


class ViewController : UIViewController { 


    var avplayerVC : AVPlayerViewController? 
    var recentlyWatchedTimer : NSTimer? 
    var lessonToWatch : Lesson? 


    override func viewDidLoad() { 
     super.viewDidLoad() 


     if let urlVideo = lessonToWatch?.lessonurl { 

      let activityIndicator = UIActivityIndicatorView(frame: CGRectMake(self.view.frame.size.width/2.0, self.view.frame.size.height/2.0, 30.0, 30.0)) 
      let asset : AVURLAsset = AVURLAsset(URL: NSURL.init(string: urlVideo)!, options: nil) 
      let keys = ["playable"]; 
      avplayerVC = AVPlayerViewController() 

      asset.loadValuesAsynchronouslyForKeys(keys) { [weak self] in 
       dispatch_async(dispatch_get_main_queue()) { [weak self] in 
        guard let vc = self, playerVC = vc.avplayerVC else { 
         return 
        } 

        playerVC.player = AVPlayer(playerItem: AVPlayerItem(asset: asset)) 
        playerVC.player?.seekToTime(kCMTimeZero) 


        print("Status 1: " + "\(playerVC.player?.status.rawValue)") 
        print(vc.view?.frame) 
        // doesn't work 

        playerVC.view.frame = vc.view.frame 
        activityIndicator.stopAnimating() 
        activityIndicator.removeFromSuperview() 
        vc.view.addSubview(playerVC.view) 
        playerVC.player?.play() 
        vc.recentlyWatchedTimer = NSTimer.scheduledTimerWithTimeInterval(20.0, target: vc, selector: "addToRecentlyWatched" , userInfo: nil, repeats: false) 
       } 
      } 

      print("In LessonPlayViewController View Did Load") 
      self.view.addSubview(activityIndicator) 
      activityIndicator.startAnimating() 
     } 

    } 


    func addToRecentlyWatched() { 
     if let lesson = lessonToWatch { 
      DataManager.sharedInstance.addRecentlyWatch(lesson) 
     } 
     recentlyWatchedTimer?.invalidate() 
    } 

    deinit { 
     print("deinit") 
     avplayerVC?.view.removeFromSuperview() 
     avplayerVC?.player = nil 
     avplayerVC = nil 
    } 

    // MARK : AVPlayerViewControllerDelegate 


} 

Подробнее о списках захвата: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID57

Редактировать

Также обратите внимание, что вы должны явно остановить воспроизведение видео при выходе контроллера представления, а не полагаться на игроке, чтобы остановить воспроизведение как часть его освобождения. I.e. в viewDidDisappear или аналогично.

Смежные вопросы