当您离开视图时如何在 Swift 中停用 AVPlayer

Posted

技术标签:

【中文标题】当您离开视图时如何在 Swift 中停用 AVPlayer【英文标题】:How to deactivate AVPlayer in Swift when you navigate away from view 【发布时间】:2020-08-01 15:28:12 【问题描述】:

我有一个从视频 url 列表到目标 Videoview 再到视频播放器的导航视图。播放器仅使用 AVPlayer(我不需要控件)在我导航到它时自动播放视频。

但是,当我点击“返回”按钮并离开 PlayerView 时,视频并没有停止播放。

感谢您对如何解决此问题的任何想法。

我已经包含了来自导航视图、通过 VideoView 和 PlayerView 的代码作为上下文。 TIA。

导航视图

NavigationView 
            List(messages, id: \.self)  message in
                NavigationLink(destination: VideoView(videoURL: URL(string:"https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/TearsOfSteel.mp4")!,  previewLength: 15)) 
                    Text(message)
                
            .navigationBarTitle("Answers")

视频查看代码

struct VideoView: UIViewRepresentable 
    var videoURL:URL
    var previewLength:Double?
    
    func makeUIView(context: Context) -> UIView 
        print("making VideoView")
        return PlayerView(frame: .zero, url: videoURL, previewLength: previewLength ?? 30)
    
    
    func updateUIView(_ uiView: UIView, context: Context) 
        
    

播放器片段

class PlayerView: UIView 
    private let playerLayer = AVPlayerLayer()
    private var previewTimer:Timer?
    var previewLength:Double
    
    init(frame: CGRect, url: URL, previewLength:Double) 
        self.previewLength = previewLength
        super.init(frame: frame)
        
        // Create the video player using the URL passed in.
        let player = AVPlayer(url: url)
        player.volume = 2 // Will play audio if you don't set to zero

// This is the AVPlayer approach to playing video with no controls
        player.play() // Set to play once created.

        // Add the player to our Player Layer
        playerLayer.player = player
        playerLayer.videoGravity = .resizeAspectFill // Resizes content to fill whole video layer.
        playerLayer.backgroundColor = UIColor.black.cgColor

        previewTimer = Timer.scheduledTimer(withTimeInterval: previewLength, repeats: false, block:  (timer) in
            player.seek(to: CMTime(seconds: 0, preferredTimescale: CMTimeScale(1)))
        )

        layer.addSublayer(playerLayer)

【问题讨论】:

不确定我是否理解反对票。如果不是合法的问题和/或可以改进措辞,欢迎输入 【参考方案1】:

这是一种可能的方法 - 在更新时使用演示模式,因为在这种情况下,它是由于导航返回而更新的。

struct VideoView: UIViewRepresentable 
    @Environment(\.presentationMode) var presentation     // << here !!

    var videoURL:URL
    var previewLength:Double?
    
    func makeUIView(context: Context) -> UIView 
        print("making VideoView")
        return PlayerView(frame: .zero, url: videoURL, previewLength: previewLength ?? 30)
    
    
    func updateUIView(_ playerView: PlayerView, context: Context) 
        // update might be called several times, so PlayerView should
        // be safe for repeated calls
        if presentation.wrappedValue.isPresented 
           playerView.play()
         else 
           playerView.stop()
                   
    

PlayerView 应该更新以访问播放器

class PlayerView: UIView 
    private let playerLayer = AVPlayerLayer()
    private var previewTimer:Timer?
    var previewLength:Double
    
    private var player: AVPlayer     // << make property

    init(frame: CGRect, url: URL, previewLength:Double) 
        self.previewLength = previewLength
        super.init(frame: frame)
        
        // Create the video player using the URL passed in.
        player = AVPlayer(url: url)
        player.volume = 2 // Will play audio if you don't set to zero

        // don't run .play() here !!!

        // ... other code
    

    func play() 
       player.rate = 1.0
    

    func stop() 
       player.rate = 0.0
    

【讨论】:

以上是关于当您离开视图时如何在 Swift 中停用 AVPlayer的主要内容,如果未能解决你的问题,请参考以下文章

Swift:重新加载视图控制器

斯威夫特:无法弄清楚如何保存用户离开表格视图的方式

如何离开/退出/停用Python virtualenv

Swift:如何使选项卡视图控制器按钮不显示?

FetchedResult 视图在离开视图并返回后不会更新

在后台点击 Swift 时禁用关闭弹出框