So I made a view called "VideoElement" that will play a video in the background when the parent view loads. It worked well. However, I cannot figure out how to implement a pause/resume system. I want to change a variable (var "paused") which would pause the video when true and resume playing when false. It kinda works. Specifically, when "paused" is true, the video pauses. However, when it becomes false, the video does not resume playing.
Perhaps it may have something to do the "updateUIViewController"? Also, I have no idea why "paused" must be a binding variable and not a state variable (@State does not work). Any help will be greatly appreciated. Thanks!
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) {
}
}
I wouldn't recommend creating the AVPlayer
in the body
-- that will guarantee that any time the view is re-rendered, the player will be recreated. Instead, store it somewhere that will survive re-renders. I've chosen an ObservableObject
for this.
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) {
}
}