SwiftUI AVPlayer and AVPlayerLayer during view re-creation

742 Views Asked by At

I'm creating a Mac OS app, using SwiftUI.

I have a NSViewRepresentable that wraps the AVPlayer:

class PlaybackModel {
     var player: AVPlayer!
     var playerLayer: AVPlayerLayer!

     func createPlayerLayer() -> AVPlayerLayer {
        let result = AVPlayerLayer(player: self.player)
        result.videoGravity = .resizeAspect
        result.needsDisplayOnBoundsChange = true
        result.backgroundColor = .black

        self.playerLayer = result
    }
}

struct PlayerViewAdapter: NSViewRepresentable {
    let playbackModel: PlaybackModel!
    
    func makeNSView(context: Context) -> BasePlayerView {
        return BasePlayerView(playbackModel)
    }
    
    func updateNSView(_ nsView: BasePlayerView, context: Context) {
    }
}

and the BasePlayerView uses the AVPlayerLayer as a backing layer:

class BasePlayerView: NSView {
    private var playbackModel: PlaybackModel!
    
    init(_ playbackModel: PlaybackModel) {
        self.playbackModel = playbackModel
        super.init(frame: .zero)
        
        wantsLayer = true
    }
    
    override func makeBackingLayer() -> CALayer {
        return playbackModel.playerLayer
    }
}

Initially it works fine and I can see the video playing inside the view.

Alas, there seems to be an issue during SwiftUI re-render process, when the PlayerViewAdapter.makeNSView() method gets called again for the same PlaybackModel (due to state changes), the AVPlayerLayer is not rendered in the newly created BasePlayerView.

Do I need to perform some additional action during this re-creation of the player views?

0

There are 0 best solutions below