转至下一个视图控制器后 AVPlayer 视频仍在播放

AVPlayer video still playing after segue to next view controller

我目前正在循环播放没有播放控件的 mp4 视频,有点像 gif,但有声音。但我不知道为什么当我转到下一个视图控制器时,视频仍在播放。有人知道解决这个问题的最简单方法吗?

ViewController

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)
    }
}
override func viewWillDisappear(_ animated: Bool) {

    }

如果您正在切换,这可能对您有所帮助windows;当你执行 segue 时,你将自动执行大括号中包含的函数。我对 AV 很垃圾,但是如果它在 IBAction 中不起作用,建议关闭该功能的其他一些代码可能在这里起作用。

虽然我对 Xcode 不是很好,所以里程可能会有所不同。

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

我遇到了这个问题并通过在将播放器设置为 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];
}
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()
}

当我使用 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
      }





    }