问题描述
所以我创建了一个名为“VideoElement”的视图,它会在父视图加载时在后台播放视频。它运作良好。但是,我无法弄清楚如何实现暂停/恢复系统。我想更改一个变量(var“paused”),它会在为真时暂停视频并在为假时继续播放。它有点工作。具体来说,当“paused”为真时,视频会暂停。但是,当它变为 false 时,视频不会继续播放。
也许它可能与“updateUIViewController”有关?另外,我不知道为什么“暂停”必须是绑定变量而不是状态变量(@State 不起作用)。任何帮助将不胜感激。谢谢!
import SwiftUI
import AVKit
struct VideoElement: View {
var fileName: String
@Binding var paused: Bool //this controls playback
var body: some View {
let player = AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forAuxiliaryExecutable: fileName)!))
AVPlayerControllerRepresented(player: player)
.onAppear {
player.play()
}
.onChange(of: paused,perform: { paused in
if paused {
player.pause()
}
else {
player.play() //should play the video,does not
print("resume") //this runs,so above should've run also
}
})
}
}
}
struct AVPlayerControllerRepresented : UIViewControllerRepresentable {
var player : AVPlayer
func makeUIViewController(context: Context) -> AVPlayerViewController {
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController,context: Context) {
}
}
解决方法
我不建议在 AVPlayer
中创建 body
-- 这将保证在任何时候重新渲染视图时,都会重新创建播放器。相反,将其存储在可以在重新渲染后继续存在的地方。我为此选择了 ObservableObject
。
class PlayerManager : ObservableObject {
let player = AVPlayer(url: URL(string: "https://media.w3.org/2010/05/sintel/trailer.mp4")!)
@Published private var playing = false
func play() {
player.play()
playing = true
}
func playPause() {
if playing {
player.pause()
} else {
player.play()
}
playing.toggle()
}
}
struct ContentView: View {
@StateObject var playerManager = PlayerManager()
var body: some View {
VStack {
AVPlayerControllerRepresented(player: playerManager.player)
.onAppear {
playerManager.play()
}
Button("Play/Pause") {
playerManager.playPause()
}
}
}
}
struct AVPlayerControllerRepresented : UIViewControllerRepresentable {
var player : AVPlayer
func makeUIViewController(context: Context) -> AVPlayerViewController {
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController,context: Context) {
}
}