I have created a UIViewRepresentable version of AVPlayerViewController to play movies using SwiftUI, with a provided URL and optionally enabling/disabling controls. Here is that code:
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")
}
}
}
The player is part of a detail view that is access from a List embedded in a NavigationView, like this:
NavigationView {
List {
NavigationLink(destination: DetailView(url: URL("url to movie")))
}
}
DetailView
simply instantiates PlayerViewController
with the provided url.
The problem I'm having is that if I play the movie in DetailView
, when I hit the back button to return from DetailView
to the main screen, I can still hear the audio from the movieit's clearly still playing off-screen.
Other SO questions have indicated that this is because a reference to the AVPlayer
is kept after the view is dismissed. If true, I'm not sure why; or, it doesn't seem like I have control over that.
If, after returning to the main view and hearing the video playing in the background, I then tap another list item, the playback immediately stops and I see the "deinit coordinator" debug message.
How can I stop playback when the PlayerViewController is dismissed and the user returns to the main view?