SwiftUI AVQueuePlayer无法更新playerItem

问题描述 投票:0回答:1

我正在尝试显示一个循环视频,然后允许用户点击一个按钮以显示下一个或上一个循环视频。

为什么@Binding不更新此内容?正确的/最佳的方法是什么?

我正在使用UIViewRepresentable。这是我的代码...


struct Player: UIViewRepresentable {

    var videoFileNames: [String]
    @Binding var currentItem: Int

    func makeUIView(context: Context) -> UIView {
        return PlayerView(frame: .zero, videoFileNames: videoFileNames, currentItem: currentItem)
    }

    func updateUIView(_ uiView: UIView, context: Context) {
    }
}


class PlayerView: UIView {
    private let playerLayer = AVPlayerLayer()
    private var playerLooper: AVPlayerLooper?

    init(frame: CGRect, videoFileNames: [String], currentItem: Int) {
        super.init(frame: frame)

        var playerItems = [AVPlayerItem]()
        let player = AVQueuePlayer(items: playerItems)

        for videoFileName in videoFileNames {
            guard let path = Bundle.main.path(forResource: videoFileName, ofType: "mp4") else {
                return
            }
            let videoURL = NSURL(fileURLWithPath: path)
            let playerItem = AVPlayerItem(url: videoURL as URL)
            playerItems.append(playerItem)
        }

        playerLooper = AVPlayerLooper(player: player, templateItem: playerItems[currentItem])

        player.volume = 0
        player.play()

        playerLayer.player = player
        playerLayer.videoGravity = .resizeAspectFill 

        layer.addSublayer(playerLayer)
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        playerLayer.frame = bounds
    }
}
swiftui avplayer avplayeritem avqueueplayer
1个回答
0
投票

@Binding中的更改仅导致调用updateUIView,因此您需要调整以下内容(使用伪代码,从头开始)

struct Player: UIViewRepresentable {

    var videoFileNames: [String]
    @Binding var currentItem: Int

    private var playerView: PlayerView!

    func makeUIView(context: Context) -> UIView {
        let view = PlayerView(frame: .zero, videoFileNames: videoFileNames, currentItem: currentItem)
        self.playerView = view
        return view
    }

    func updateUIView(_ uiView: UIView, context: Context) {
        self.playerView.currentItem = currentItem // update player !!
    }
}

class PlayerView: UIView {
   var currentItem: Int {
       didSet {
          // .. refresh here internal player
       }
   }

    init(frame: CGRect, videoFileNames: [String], currentItem: Int) {
        super.init(frame: frame)

        self.currentItem = currentItem
        var playerItems = [AVPlayerItem]()

   // .. other code

© www.soinside.com 2019 - 2024. All rights reserved.