在 SwiftUI 中更改 AVPlayer 源?
Posted
技术标签:
【中文标题】在 SwiftUI 中更改 AVPlayer 源?【英文标题】:Change AVPlayer source in SwiftUI? 【发布时间】:2021-02-04 11:56:23 【问题描述】:我有一个 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
,但不会改变播放器的视频/来源!
我还有什么需要做的吗?
【问题讨论】:
【参考方案1】:首先,创建一个合适的 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 中绑定你的播放器
播放器视图
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)
【讨论】:
这个需要本地网址吗:AVPlayer(url: Bundle.main.url(forResource: "https://www.w3schools.com/html/movie.mp4", withExtension: "mp4")!)
没有。你可以直接使用AVPlayer(url: URL(string: "https://media.w3.org/2010/05/sintel/trailer.mp4")!)
我用于测试目的并使用本地视频。
有一个问题,我不知道如何解决。加载新视频时,它不会循环播放。基本上通知变得无用,视频只播放一次。
你知道为什么如果源发生变化视频停止循环吗?
尚未检查,将检查以上是关于在 SwiftUI 中更改 AVPlayer 源?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 SwiftUI 在 VStack 中显示我的 AVPlayer
SwiftUI VideoPlayer,更改默认黑色背景/侧面空间
SwiftUI MacOS App AVPlayer 不适用于视频 URL