2016-06-29 6 views
0

Я работаю над приложением tvOS с помощью быстрого доступа. Я использую AVPlayerViewController для воспроизведения видео после демонстрационного приложения Apple (каталог UIKit (tvOS): создание и настройка элементов управления UIKit). Все работает нормально, но приложение вводит фон на передний план во время воспроизведения видео, а вперед и назад не работает, и одна и та же проблема генерируется, если пользователь может перейти в спящий режим. Эта проблема также генерируется в демонстрационном приложении Apple.Вперед и назад не работает, когда приложение вводит фон на передний план во время воспроизведения видео в tvOS

Я не понимаю, почему эта проблема порождает. Пожалуйста, предложите мне, как его решить.

import UIKit 
    import Foundation 
    import AVKit 

    class ViewController: UIViewController ,AVPlayerViewControllerDelegate{ 
     let playerController = AVPlayerViewController() 
     var playerObj:AVPlayer! 
     var asset:AVAsset! 
     var playerItem:AVPlayerItem! 
     override func viewDidLoad() { 
      super.viewDidLoad() 
      // Do any additional setup after loading the view, typically from a nib. 
     self.playVideo("http://p.events-delivery.apple.com.edgesuite.net/1509pijnedfvopihbefvpijlkjb/m3u8/hls_vod_mvp.m3u8") 
     } 
    override func viewWillAppear(animated: Bool) { 
     playerController.delegate = self 
    } 
     //MARK:- Play Video Method. 
     func playVideo(videoURL:String) { 
      print("video URL========\(videoURL)") 

      self.asset = AVAsset(URL: NSURL(string: videoURL)!) as AVAsset 
      self.playerItem = AVPlayerItem(asset: self.asset) 
      self.playerObj = AVPlayer(playerItem: self.playerItem) 
      self.playerController.player = self.playerObj 
      playerController.view.frame = CGRectMake(0.0, 0.0, UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height) 
      playerController.delegate = self 
      self.view.addSubview(playerController.view) 
      self.playerController.showsPlaybackControls = true 
      self.playerItem.addObserver(self, forKeyPath: "status", options: NSKeyValueObservingOptions.New, context: nil) 
      self.playerController.player!.play() 
      //self.playerController.player!.play() 


     } 
     override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>){ 

      if object as? NSObject == playerItem && (keyPath! as NSString).isEqualToString("status") { 

       if (playerItem?.status == AVPlayerItemStatus.ReadyToPlay) { 
         print("Player Ready to play") 
       } 
       if (playerItem?.status == AVPlayerItemStatus.Failed) || (playerItem?.status == AVPlayerItemStatus.Unknown) { 

         print("Player getting play error") 
       } 
      } 
     } 


     override func didReceiveMemoryWarning() { 
      super.didReceiveMemoryWarning() 
      // Dispose of any resources that can be recreated. 
     } 


    } 
+0

Объем контекста кода, который вы дали, недостаточен, чтобы действительно придумать жизнеспособное решение для вас, потому что я не могу определить полный контекст. Из моего опыта работы с AVPlayer я рекомендую сделать это переменной класса, но кажется, что вместо этого вы делаете эту переменную метода. Если это так, то, вероятно, ваша функция не будет удерживаться на AVPlayer всякий раз, когда метод завершается. Apple даже предполагает, что вы создаете переменную класса для AVPlayer, чтобы «удерживать» ссылку AVPlayer для жизненного цикла вашего приложения. – user1171911

+0

Я пробовал с переменной класса, но проблема такая же. – vipulk617

+0

Я все же рискну сказать, что ваш класс освобождает делегата для приема сообщений в прямом и обратном направлении. Это может означать, что ваш класс нераспределяется, когда приложение входит в фоновый режим. Обычно для решения этой проблемы я создаю одноэлементный класс для управления воспроизведением аудио/видео, чтобы я мог гарантировать, что мое приложение сильно привязается к моему AVPlayer на протяжении всего жизненного цикла приложения. – user1171911

ответ

0

попробуйте это ... возможно, не «лучшее» решение, но оно показывает, что я говорю о жизненном цикле контроллера представления.

Боковое примечание, я бы предположил, что вы всегда вызываете super.viewWillAppear (анимированные) внутри своих переопределенных функций для контроллера вида.

import UIKit 
import Foundation 
import AVKit 
import AVFoundation 

class ViewController: UIViewController ,AVPlayerViewControllerDelegate{ 
    let playerController = AVPlayerViewController() 
    var playerObj:AVPlayer = AVPlayer() 
    var asset:AVAsset! 
    var playerItem:AVPlayerItem! 
    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
    } 
override func viewWillAppear(animated: Bool) { 
    super.viewWillAppear(animated) // always call this 
    playerController.delegate = self 
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(setDelegateOnForground), name: "application_forgrounded", object: nil) 
} 

override func viewDidAppear(animated: Bool) { 
    super.viewDidAppear(animated) // always call this 
    // check the player rate if 0 means it's paused/not playing 

если playerObj.rate == 0 { playVideo ("http://p.events-delivery.apple.com.edgesuite.net/1509pijnedfvopihbefvpijlkjb/m3u8/hls_vod_mvp.m3u8") }} // МАРК: - Играть метод видео. func playVideo (videoURL: String) { print ("video URL ======== (videoURL)") self.asset = AVAsset (URL: NSURL (строка: videoURL)!) Как AVAsset self. playerItem = AVPlayerItem (актив: self.asset) self.playerObj = AVPlayer (playerItem: self.playerItem) self.playerController.player = self.playerObj playerController.view.frame = CGRectMake (0.0, 0.0, UIScreen.mainScreen () .bounds.width, UIScreen.mainScreen(). bounds.height) self.view.addSubview (playerController.view) self.playerController.showsPlaybackControls = true self.playerItem.addObserver (self, forKeyPath: «status», опции: NSKeyValueObservingOptions.New, контекст: nil) self.playerC ontroller.player! .play() //self.playerController.player!.play()

} 

func setDelegateOnForground() { 
    playerController.delegate = self 
} 
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>){ 

    if object as? NSObject == playerItem && (keyPath! as NSString).isEqualToString("status") { 

     if (playerItem?.status == AVPlayerItemStatus.ReadyToPlay) { 
      print("Player Ready to play") 
     } 
     if (playerItem?.status == AVPlayerItemStatus.Failed) || (playerItem?.status == AVPlayerItemStatus.Unknown) { 

      print("Player getting play error") 
     } 
    } 
} 


override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Dispose of any resources that can be recreated. 
} 

}

в вашем AppDelegate.swift в

func applicationDidBecomeActive(application: UIApplication) { 
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 
    NSNotificationCenter.defaultCenter().postNotification(NSNotification(name: "application_forgrounded", object: nil)) 
} 

это будет гарантировать set your delegate

+0

Этот код не работает. Если приложение вводит фон на передний план, то viewWillAppear не вызывает. – vipulk617

+0

отредактировал мой ответ извините за это. – user1171911

+0

поэтому после публикации правильной версии он работает для меня. Я могу идти туда и обратно в видео с помощью функции пропуска – user1171911