SwiftUI AVPlayer - 如何暂停和恢复播放?

问题描述

所以我创建了一个名为“VideoElement”的视图,它会在父视图加载时在后台播放视频。它运作良好。但是,我无法弄清楚如何实现暂停/恢复系统。我想更改一个变量(var“paused”),它会在为真时暂停视频并在为假时继续播放。它有点工作。具体来说,当“paused”为真时,视频会暂停。但是,当它变为 false 时,视频不会继续播放。

也许它可能与“updateUIViewController”有关?另外,我不知道为什么“暂停”必须是绑定变量而不是状态变量(@State 不起作用)。任何帮助将不胜感激。谢谢!

import SwiftUI
import AVKit

struct VideoElement: View {

    var fileName: String
    @Binding var paused: Bool //this controls playback

    var body: some View {
    
        let player = AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forAuxiliaryExecutable: fileName)!))
    
        AVPlayerControllerRepresented(player: player)
            .onAppear {
                player.play()
            }
            .onChange(of: paused,perform: { paused in
                if paused {
                    player.pause()
                }
                else {
                    player.play() //should play the video,does not
                    print("resume") //this runs,so above should've run also
                }
            })
        }  
    }
}

struct AVPlayerControllerRepresented : UIViewControllerRepresentable {

    var player : AVPlayer

    func makeUIViewController(context: Context) -> AVPlayerViewController {
        let controller = AVPlayerViewController()
        controller.player = player
        controller.showsPlaybackControls = false
        return controller
    }

    func updateUIViewController(_ uiViewController: AVPlayerViewController,context: Context) {
    }
}

解决方法

我不建议在 AVPlayer 中创建 body -- 这将保证在任何时候重新渲染视图时,都会重新创建播放器。相反,将其存储在可以在重新渲染后继续存在的地方。我为此选择了 ObservableObject

class PlayerManager : ObservableObject {
    let player = AVPlayer(url: URL(string: "https://media.w3.org/2010/05/sintel/trailer.mp4")!)
    @Published private var playing = false
    
    func play() {
        player.play()
        playing = true
    }
    
    func playPause() {
        if playing {
            player.pause()
        } else {
            player.play()
        }
        playing.toggle()
    }
}

struct ContentView: View {
    @StateObject var playerManager = PlayerManager()
    
    var body: some View {
        VStack {
            AVPlayerControllerRepresented(player: playerManager.player)
                .onAppear {
                    playerManager.play()
                }
            Button("Play/Pause") {
                playerManager.playPause()
            }
        }
    }
}

struct AVPlayerControllerRepresented : UIViewControllerRepresentable {
    var player : AVPlayer
    
    func makeUIViewController(context: Context) -> AVPlayerViewController {
        let controller = AVPlayerViewController()
        controller.player = player
        controller.showsPlaybackControls = false
        return controller
    }
    
    func updateUIViewController(_ uiViewController: AVPlayerViewController,context: Context) {
        
    }
}