Skip to content

Instantly share code, notes, and snippets.

@zwaldowski
Last active June 9, 2023 00:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zwaldowski/8cc827f0c59a1d71e5a90a7241bd8800 to your computer and use it in GitHub Desktop.
Save zwaldowski/8cc827f0c59a1d71e5a90a7241bd8800 to your computer and use it in GitHub Desktop.
struct AVPlayerViewWrapper: UIViewControllerRepresentable {
var url: URL
var shouldStartPlayback: Bool
func makeUIViewController(context: Context) -> AVPlayerViewController {
let controller = AVPlayerViewController()
controller.player = AVPlayer(url: url)
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
if shouldStartPlayback {
uiViewController.player?.play()
}
}
}
struct VideoPlayerView: View {
var url: URL
@State var shouldStartPlayback = false
var body: some View {
VStack {
AVPlayerViewWrapper(url: url, shouldStartPlayback: shouldStartPlayback)
.aspectRatio(contentMode: .fit)
.padding(.vertical, 0)
.onAppear {
shouldStartPlayback = true
}
Spacer()
}
}
}
struct VideoPlayerView_Previews: PreviewProvider {
static var previews: some View {
VideoPlayerView(url: URL(string: "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8")!)
}
}
struct AVPlayerViewWrapper: UIViewControllerRepresentable {
var url: URL
@Binding var isPlaying: Bool
func makeUIViewController(context: Context) -> AVPlayerViewController {
let player = AVPlayer(url: url)
NotificationCenter.default.addObserver(context.coordinator, selector: #selector(Coordinator.noteRateDidChange), name: AVPlayer.rateDidChangeNotification, object: player)
let controller = AVPlayerViewController()
controller.player = player
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
if isPlaying {
uiViewController.player?.play()
} else {
uiViewController.player?.pause()
}
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
class Coordinator {
var isPlaying: Binding<Bool>?
@objc func noteRateDidChange(_ note: Notification) {
guard let player = note.object as? AVPlayer else { return }
isPlaying?.wrappedValue = player.rate != 0
}
}
}
struct VideoPlayerView: View {
var url: URL
@State var isPlaying = false
var body: some View {
VStack {
AVPlayerViewWrapper(url: url, isPlaying: $isPlaying)
.aspectRatio(contentMode: .fit)
.padding(.vertical, 0)
.onAppear {
isPlaying = true
}
Spacer()
}
}
}
struct VideoPlayerView_Previews: PreviewProvider {
static var previews: some View {
VideoPlayerView(url: URL(string: "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8")!)
}
}
@zwaldowski
Copy link
Author

Additional exercise for the reader: it would likely be prudent for updateUIViewController to check if the url has changed, as the system can and will reuse representable views with different parameters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment