Home > Mobile >  SwiftUI pass parameter to Class from UIViewRepresentable
SwiftUI pass parameter to Class from UIViewRepresentable

Time:09-01

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
    }
}

  • Related