I have a question that I think is quite simple and yet I get stuck, so I come to ask for help and maybe it could be other people !
I want to loop a video, but i've problem, i need to pass a var to a struct then a class like :
struct FinalPreview: View {
var url: URL
PlayerView(url: url)
.aspectRatio(contentMode: .fill)
.frame(width: size.width, height: size.height)
.clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous))
.onAppear{
if player.currentItem == nil {
let item = AVPlayerItem(url: url)
player.replaceCurrentItem(with: item)
}
DispatchQueue.main.asyncAfter(deadline: .now() 0.5, execute: {
player.play()
})
}
}
struct PlayerView: UIViewRepresentable {
var url: URL
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PlayerView>) {
}
func makeUIView(context: Context) -> UIView {
return PlayerUIView(frame: .zero)
}
}
class PlayerUIView: UIView {
private let playerLayer = AVPlayerLayer()
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(frame: CGRect) {
super.init(frame: frame)
// Load the resource
let fileUrl = "MY URL VAR FROM PlayerView"
// Setup the player
let player = AVPlayer(url: fileUrl)
playerLayer.player = player
playerLayer.videoGravity = .resizeAspectFill
layer.addSublayer(playerLayer)
// Setup looping
player.actionAtItemEnd = .none
// Start the movie
player.play()
}
@objc
func playerItemDidReachEnd(notification: Notification) {
playerLayer.player?.seek(to: CMTime.zero)
}
override func layoutSubviews() {
super.layoutSubviews()
playerLayer.frame = bounds
}
}
It's to loop a video.
I'm also looking to hide AVPlayer controls by using :
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) {
}
}
To hide the controls, it works very well, I don't know how to combine both...
Thank you.
CodePudding user response:
You actually don't need 3 different types, just a single UIViewControllerRepresentable
with a url
:
import AVKit
import SwiftUI
struct PlayerView: UIViewControllerRepresentable {
var url: URL
func makeUIViewController(context: Context) -> AVPlayerViewController {
// create a looping auto-starting video player:
let player = AVPlayer(url: url)
player.actionAtItemEnd = .none
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue: .main) { [weak player] _ in
player?.seek(to: .zero)
}
DispatchQueue.main.asyncAfter(deadline: .now() 0.5) { [weak player] in
player?.play()
}
// use that player in a view controller:
let controller = AVPlayerViewController()
controller.player = player
controller.videoGravity = .resizeAspectFill
controller.showsPlaybackControls = false
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {}
}
struct PlayerView_Previews: PreviewProvider {
static var previews: some View {
PlayerView(url: someVideoURL) // replace the URL with your own
}
}