Skip to content

Instantly share code, notes, and snippets.

@sharukmsd
Last active August 8, 2023 07:27
Show Gist options
  • Save sharukmsd/e2fcf8f35a1ed9f57a0e2d742846262d to your computer and use it in GitHub Desktop.
Save sharukmsd/e2fcf8f35a1ed9f57a0e2d742846262d to your computer and use it in GitHub Desktop.
SwiftUI video player with loading indicator
import AVFoundation
import AVKit
import SwiftUI
struct VideoPlayer: UIViewRepresentable {
var videoURL: URL
let videoPlayerView = ActivityIndicatorPlayer()
func makeUIView(context: Context) -> ActivityIndicatorPlayer {
let player = AVPlayer(url: videoURL)
videoPlayerView.setPlayer(player: player)
videoPlayerView.startLoading()
player.addObserver(context.coordinator, forKeyPath: "status", options: [.old, .new], context: nil)
return videoPlayerView
}
func updateUIView(_ uiView: ActivityIndicatorPlayer, context: Context) {}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject {
var parent: VideoPlayer
init(_ parent: VideoPlayer) {
self.parent = parent
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "status", let change = change, let newValue = change[NSKeyValueChangeKey.newKey] as? Int {
if newValue == AVPlayer.Status.readyToPlay.rawValue {
parent.videoPlayerView.stopLoading()
}
}
}
}
}
class ActivityIndicatorPlayer: UIView {
private let playerViewController = AVPlayerViewController()
private let activityIndicator = UIActivityIndicatorView(style: .large)
override init(frame: CGRect) {
super.init(frame: frame)
configurePlayerView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
configurePlayerView()
}
private func configurePlayerView() {
addSubview(playerViewController.view)
addSubview(activityIndicator)
playerViewController.view.translatesAutoresizingMaskIntoConstraints = false
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
playerViewController.view.topAnchor.constraint(equalTo: topAnchor),
playerViewController.view.leadingAnchor.constraint(equalTo: leadingAnchor),
playerViewController.view.trailingAnchor.constraint(equalTo: trailingAnchor),
playerViewController.view.bottomAnchor.constraint(equalTo: bottomAnchor),
activityIndicator.centerXAnchor.constraint(equalTo: centerXAnchor),
activityIndicator.centerYAnchor.constraint(equalTo: centerYAnchor)
])
}
func setPlayer(player: AVPlayer?) {
playerViewController.player = player
}
func startLoading() {
activityIndicator.startAnimating()
}
func stopLoading() {
activityIndicator.stopAnimating()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment