在SwiftUI中更改AVPlayer源?

  • 本文关键字:AVPlayer SwiftUI swiftui
  • 更新时间 :
  • 英文 :


我有一个AVPlayer,在我的SwiftUI应用程序的后台播放视频,工作正常。

但是我需要允许用户通过点击按钮来改变视频。

这是我播放视频的代码:

var player = AVPlayer()
var bgVideoURL = "https://www.w3schools.com/html/movie.mp4"

struct PlayerView: UIViewRepresentable {
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PlayerView>) {
}
func makeUIView(context: Context) -> UIView {
return PlayerUIView(frame: .zero)
}
}
class PlayerUIView: UIView {
private let playerLayer = AVPlayerLayer()
override init(frame: CGRect) {
super.init(frame: frame)
let url = URL(string: bgVideoURL)!
player = AVPlayer(url: url)
player.actionAtItemEnd = .none

player.play()
playerLayer.player = player
playerLayer.videoGravity = .resizeAspectFill
NotificationCenter.default.addObserver(self,
selector: #selector(playerItemDidReachEnd(notification:)),
name: .AVPlayerItemDidPlayToEndTime,
object: player.currentItem)
layer.addSublayer(playerLayer)
}


@objc func playerItemDidReachEnd(notification: Notification) {
if let playerItem = notification.object as? AVPlayerItem {
playerItem.seek(to: .zero, completionHandler: nil)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
playerLayer.frame = bounds
}
}

我是这样播放视频的

var body: some View {
PlayerView()
.edgesIgnoringSafeArea(.all)
}

我需要改变视频按钮点击/点击,所以我试了这个:

.onTapGesture {
player.pause()
player.seek(to: .zero)
bgVideoURL = "https://media.w3.org/2010/05/sintel/trailer.mp4"
player.play()

}

上面的代码将重新启动player,但它不会改变播放器的视频/源!

还有什么我需要做的吗?

首先,创建一个合适的PlayerUIView类(删除全局变量等)

PlayerUIView

class PlayerUIView: UIView {

// MARK: Class Property

let playerLayer = AVPlayerLayer()

// MARK: Init

override init(frame: CGRect) {
super.init(frame: frame)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

init(player: AVPlayer) {
super.init(frame: .zero)
self.playerSetup(player: player)
}

deinit {
NotificationCenter.default.removeObserver(self)
}

// MARK: Life-Cycle

override func layoutSubviews() {
super.layoutSubviews()
playerLayer.frame = bounds
}

// MARK: Class Methods

private func playerSetup(player: AVPlayer) {
playerLayer.player = player
player.actionAtItemEnd = .none
layer.addSublayer(playerLayer)

self.setObserver()
}

func setObserver() {
NotificationCenter.default.removeObserver(self)
NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidReachEnd(notification:)),
name: .AVPlayerItemDidPlayToEndTime,
object: playerLayer.player?.currentItem)
}

@objc func playerItemDidReachEnd(notification: Notification) {
if let playerItem = notification.object as? AVPlayerItem {
playerItem.seek(to: .zero, completionHandler: nil)
self.playerLayer.player?.play()
}
}
}

现在,使用@Binding绑定播放器在PlayerView

PlayerView

struct PlayerView: UIViewRepresentable {

@Binding var player: AVPlayer

func makeUIView(context: Context) -> PlayerUIView {
return PlayerUIView(player: player)
}

func updateUIView(_ uiView: PlayerUIView, context: UIViewRepresentableContext<PlayerView>) {
uiView.playerLayer.player = player

//Add player observer.
uiView.setObserver()
}
}

最后,在内容视图中创建AVPlayer对象,用AVPlayer更改你的新URL。

struct PlayerContentView: View {

@State private var player = AVPlayer(url: URL(string: "https://media.w3.org/2010/05/sintel/trailer.mp4")!)

var body: some View {
PlayerView(player: $player)
.onTapGesture {
player.pause()
player.seek(to: .zero)

player = AVPlayer(url: Bundle.main.url(forResource: "temp_video", withExtension: "mp4")!) // or AVPlayer(url: URL(string: "https://media.w3.org/2010/05/sintel/trailer.mp4")!)
player.play()

}
.onAppear {
player.play()
}
.edgesIgnoringSafeArea(.all)
}
}

最新更新