Search code examples
swiftswiftuiavplayeravplayerviewcontroller

AVPlayer.currentTime() returns zero


Situation

I want to implement a AVPlayer with controls. This worked quit well for me:

struct AVPlayerView: UIViewControllerRepresentable {
    var videoURL: URL
    var position: Int64
    
    private var player: AVPlayer {
        return AVPlayer(url: videoURL)
    }

    func updateUIViewController(_ playerController: AVPlayerViewController, context: Context) {
        print("updateUIView!")
    }
    
    func makeUIViewController(context: Context) -> AVPlayerViewController {
        let playerController = AVPlayerViewController()
        playerController.modalPresentationStyle = .fullScreen
        playerController.player = player
        playerController.player?.seek(to: CMTimeMake(value: 1320, timescale: 1))
        playerController.player?.play()
        return playerController
    }
}

In view:

VPlayerView(videoURL: URL(string: videoURL)!, position: startPosition).transition(.move(edge: .bottom)).edgesIgnoringSafeArea(.all)

I also need to get the current time from the AVPlayer when it disappear. I don't seem to understand how it works at all... Every time I try to get the currentTime() it returns 0.

I try it in two ways, first instantiate the AVPlayerView as var and to define the player variable as none-private. The second way, was to define a @State variable and to @Bind it to the struct. On this way, I hoped to trigger the updateUIViewController but no luck. (Got this from here --> https://stackoverflow.com/a/58614780/15797011)

Questions

  1. How can I get the currentTime() from this construction?
  2. How can I trigger the updateUIViewController?

Solution

  • Found the Solution, thx to: jnpdx

    1. How can I get the currentTime() from this construction?

    If you are able to call the currentTime() from the current item, then it would work. My fault was, I was calling this on the wrong "level". Add it to the updateUIViewController function.

    func updateUIViewController(_ playerController: AVPlayerViewController, context: Context) {
            print("Current time in sec: \(playerController.player?.currentTime().seconds)")
    }
    
    1. How can I trigger the updateUIViewController?

    Thx to jnpdx, I try it in another way: Set the state in the view where the AVPlayer will be displayed:

    struct PlayerModal: View {
        @State var videoPos: Double = 0.0
        
        var body: some View {
            AVPlayerView(videoURL: URL(string: videoURL)!, position: startPosition, videoPos: videoPos)
        }
    }
    
    struct AVPlayerView: UIViewControllerRepresentable {
        var videoURL: URL
        var position: Int64
        var videoPos: Double
        
        private var player: AVPlayer {
            return AVPlayer(url: videoURL)
        }
    
        func updateUIViewController(_ playerController: AVPlayerViewController, context: Context) {
            print("Current time in sec: \(playerController.player?.currentTime().seconds)")
        }
        
        func makeUIViewController(context: Context) -> AVPlayerViewController {
            let playerController = AVPlayerViewController()
            playerController.modalPresentationStyle = .fullScreen
            playerController.player = player
            playerController.player?.seek(to: CMTimeMake(value: 1320, timescale: 1))
            playerController.player?.play()
            return playerController
        }
    }
    

    And before jnpdx gave me the hint, I was playing around with @Binding on the AVPlayerView. This doesn't work. (hope someone can explain me, why...)