如何在解雇后停止播放 AVPlayerViewController 作为 UIViewRepresentable?

Posted

技术标签:

【中文标题】如何在解雇后停止播放 AVPlayerViewController 作为 UIViewRepresentable?【英文标题】:How to stop playback of AVPlayerViewController as UIViewRepresentable after dismissal? 【发布时间】:2019-11-04 16:34:49 【问题描述】:

我创建了一个 UIViewRepresentable 版本的 AVPlayerViewController 来使用 SwiftUI 播放电影,并提供了 URL 和可选的启用/禁用控件。这是代码:

struct PlayerViewController: UIViewRepresentable 
    // Provide the player to this swiftui view
    var url: URL
    var showControls: Bool = true

    typealias UIViewType = UIView

    func makeUIView(context: UIViewRepresentableContext<PlayerViewController>) -> UIView 
        let controller = AVPlayerViewController()
        controller.player = AVPlayer(url: url)
        controller.showsPlaybackControls = showControls
        context.coordinator.controller = controller
        return controller.view
    

    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PlayerViewController>) 
    

    func makeCoordinator() -> PlayerViewController.Coordinator 
        Coordinator()
    

    class Coordinator: NSObject 
        var controller: AVPlayerViewController?

        deinit 
            print("deinit coordinator")
        
    

播放器是从嵌入在 NavigationView 中的列表访问的详细视图的一部分,如下所示:

NavigationView 
    List 
        NavigationLink(destination: DetailView(url: URL("url to movie")))
    

DetailView 只是用提供的 url 实例化 PlayerViewController

我遇到的问题是,如果我在 DetailView 中播放电影,当我点击返回按钮从 DetailView 返回到主屏幕时,我仍然可以听到电影中的音频它显然仍在播放屏幕外。

其他 SO 问题表明这是因为在关闭视图后保留了对 AVPlayer 的引用。如果是真的,我不知道为什么;或者,我似乎无法控制。

如果在返回主视图并听到后台播放的视频后,我点击另一个列表项,播放立即停止并且我看到“deinit coordinator”调试消息。

当 PlayerViewController 被关闭并且用户返回主视图时如何停止播放?

【问题讨论】:

【参考方案1】:

你可以通过viewWillDisappear方法通过添加扩展来暂停播放

extension AVPlayerViewController 
    open override func viewWillDisappear(_ animated: Bool) 
        super.viewWillDisappear(animated)
        self.player?.pause()
        print("*** Video paused.")
    

【讨论】:

此解决方案在进入全屏模式时会产生问题。它将再次暂停视频。 文档明确指出 The framework doesn’t support subclassing AVPlayerViewController. 这意味着你甚至不应该覆盖,除非你喜欢麻烦 这在这种情况下不起作用,因为 SwiftUI 不会调用控制器上的任何方法。【参考方案2】:

您可能希望拥有自己的UIViewControllerType,而不是AVPlayerViewController,而是自定义ContainerViewController。然后你添加一个AVPlayerViewController 的实例作为它的子元素,并保留对它的引用。 然后在ContainerViewController 的覆盖viewXDisappear 中,您将拥有avPlayerViewControllerInstance.stop()。 应该这样做。

【讨论】:

以上是关于如何在解雇后停止播放 AVPlayerViewController 作为 UIViewRepresentable?的主要内容,如果未能解决你的问题,请参考以下文章

如何在游戏状态为暂停时停止游戏的播放列表,并在游戏完成暂停状态后重新播放? JavaScript

如何在使用 Flash 停止播放视频后自动录制视频响应

即使关闭后如何停止弹出视频的视频播放背景

使用Light YouTube嵌入模态(从基础显示) - 如何在模态窗口关闭后停止视频播放?

关闭阶段JavaFX后如何停止WebEngine?

FFMpeg Discordjs Music Bot 在随机时间后随机停止播放音乐