切换到下一个视图控制器后,AVPlayer 视频仍在播放
Posted
技术标签:
【中文标题】切换到下一个视图控制器后,AVPlayer 视频仍在播放【英文标题】:AVPlayer video still playing after segue to next view controller 【发布时间】:2018-02-12 02:17:42 【问题描述】:我目前正在循环播放我的 mp4 视频,没有播放控件,有点像 gif,但有声音。但我不知道为什么当我转到下一个视图控制器时,视频仍在播放。有人知道解决这个问题的最简单方法吗?
视图控制器
import UIKit
import AVKit
import AVFoundation
fileprivate var playerObserver: Any?
class ScoreController: UIViewController
@IBOutlet var label: UILabel!
override func viewDidLoad()
super.viewDidLoad()
let returnValue: Int = UserDefaults.standard.integer(forKey: "userScore")
label.text = "Your Score: \(returnValue)/30"
do
try AVAudiosession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
let path = Bundle.main.path(forResource: "Innie-Kiss", ofType:"mp4")
let player = AVPlayer(url: URL(fileURLWithPath: path!))
let resetPlayer =
player.seek(to: kCMTimeZero)
player.play()
playerObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue: nil) notification in resetPlayer()
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false
self.addChildViewController(controller)
let screenSize = UIScreen.main.bounds.size
let videoFrame = CGRect(x: 0, y: 130, width: screenSize.width, height: (screenSize.height - 130) / 2)
controller.view.frame = videoFrame
self.view.addSubview(controller.view)
player.play()
catch
override func viewDidDisappear(_ animated: Bool)
super.viewDidDisappear(animated)
fileprivate var player: AVPlayer?
didSet player?.play()
deinit
guard let observer = playerObserver else return
NotificationCenter.default.removeObserver(observer)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
@IBAction func doneButton(_ sender: Any)
self.performSegue(withIdentifier: "done", sender: self)
【问题讨论】:
在移动到下一个视图控制器之前停止播放器。 什么是合适的代码? 尝试使用这个:AVAudioSession.setActive(false, with: AVAudioSessionSetActiveOptions.notifyOthersOnDeactivation) 将此代码粘贴到我的按钮操作右侧 是的,当你移动到下一个vc时,先执行这个。 【参考方案1】:在 viewWillDisapper() 或 segue 的按钮操作中这样做:
NotificationCenter.default.removeObserver(self)
还将它从 viewDidLoad() 移动到一些函数,例如:
var player: AVPlayer?
func audioPlayer()
do
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
let path = Bundle.main.path(forResource: "Innie-Kiss", ofType:"mp4")
player = AVPlayer(url: URL(fileURLWithPath: path!))
let resetPlayer =
self.player?.seek(to: kCMTimeZero)
self.player?.play()
playerObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player?.currentItem, queue: nil) notification in resetPlayer()
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false
self.addChildViewController(controller)
let screenSize = UIScreen.main.bounds.size
let videoFrame = CGRect(x: 0, y: 130, width: screenSize.width, height: (screenSize.height - 130) / 2)
controller.view.frame = videoFrame
self.view.addSubview(controller.view)
player?.play()
catch
并使玩家对象成为全局变量。 var player = AVPlayer?
和 viewWillDisappear
使其成为 nil
。
所以你的 viewWillDisappear 应该是这样的:
override func viewWillDisappear(_ animated: Bool)
NotificationCenter.default.removeObserver(self)
if player != nil
player?.replaceCurrentItem(with: nil)
player = nil
【讨论】:
奇怪...我做了你所做的,音频仍然循环:/ 使 AVPlayerViewController 对象也成为全局对象并释放它。你能也显示你更新的内容吗? 并在播放器为零之前停止播放器。 好的,我尝试将我的 AVPlayerViewController 也设置为全局,但发生错误,您可以查看此图像以获取更多信息和我所做的代码 - ibb.co/dODigS ibb.co/jAfkvn 另外,swift 不允许 player.stop() 所以我不能这样做【参考方案2】:override func viewWillDisappear(_ animated: Bool)
如果您正在切换窗口,这可能会对您有所帮助;在执行 segue 时,您将自动执行大括号中包含的函数。我对 AV 很垃圾,但是如果它在 IBAction 中不起作用,建议关闭该功能的其他一些代码可能在这里起作用。
不过,我对 Xcode 不是很好,所以里程可能会有所不同。
【讨论】:
我确实尝试过,但无济于事。即使我去下一个视图控制器,它仍然可以听到:/【参考方案3】:我遇到了这个问题,并通过在将 player 设置为 nil 之前添加此行来解决它:
[self.player 暂停];
这是我的观点WillDisapear:
- (void)viewWillDisappear:(BOOL)animated
[[NSNotificationCenter defaultCenter] removeObserver:self
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.player];
[self.player removeObserver:self forKeyPath:@"rate"];
[self.player removeTimeObserver:self.playerObserver];
self.playerObserver = nil;
[self.player pause];
self.player = nil;
[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationPortrait) forKey:@"orientation"];
[UINavigationController attemptRotationToDeviceOrientation];
[StayfilmApp restrictOrientation:YES];
【讨论】:
【参考方案4】:class ScoreController: UIViewController
@IBOutlet var label: UILabel!
var player: AVPlayer?
override func viewDidLoad()
super.viewDidLoad()
let returnValue: Int = UserDefaults.standard.integer(forKey: "userScore")
label.text = "Your Score: \(returnValue)/30"
do
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
let path = Bundle.main.path(forResource: "Innie-Kiss", ofType:"mp4")
player = AVPlayer(url: URL(fileURLWithPath: path!))
let resetPlayer =
player.seek(to: kCMTimeZero)
player.play()
playerObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue: nil) notification in resetPlayer()
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false
self.addChildViewController(controller)
let screenSize = UIScreen.main.bounds.size
let videoFrame = CGRect(x: 0, y: 130, width: screenSize.width, height: (screenSize.height - 130) / 2)
controller.view.frame = videoFrame
self.view.addSubview(controller.view)
player.play()
catch
override func viewDidDisappear(_ animated: Bool)
super.viewDidDisappear(animated)
player.pause()
fileprivate var player: AVPlayer?
didSet player?.play()
deinit
guard let observer = playerObserver else return
NotificationCenter.default.removeObserver(observer)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
@IBAction func doneButton(_ sender: Any)
self.performSegue(withIdentifier: "done", sender: self)
显着变化:
var player: AVPlayer?
还有
override func viewDidDisappear(_ animated: Bool)
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(self)
player?.pause()
【讨论】:
【参考方案5】:当我使用 segue 转到下一个 ViewController 时,我遇到了同样的问题,然后我通过使用此代码将当前代码与 swift 一起使用
@IBAction func next(_ sender: Any)
let vc = self .storyboard?.instantiateViewController(withIdentifier:"ViewControllerAA") as! ViewControllerAA
self.present(vc,animated: true,completion: nil)
但问题没有解决,然后我用这段代码去下一个VC,我的问题解决了,视频的背景声音停止了,代码如下
@IBAction func next(_ sender: Any)
if let vc = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllerAA") as? ViewControllerAA
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = vc
【讨论】:
以上是关于切换到下一个视图控制器后,AVPlayer 视频仍在播放的主要内容,如果未能解决你的问题,请参考以下文章
AVPlayer replaceCurrentItemWithPlayerItem 打破 UIViewAnimation