我在尝试查找视频的结束时间时遇到错误
import SwiftUI
import AVKit
struct ContentViewC: View {
private let player = AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: "videoToPlay", ofType: "mp4")!))
// throw multiple errors
NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying), name: .AVPlayerItemDidPlayToEndTime, object: nil)
func playerDidFinishPlaying(note: NSNotification) {
print("video finished")
// how to change view here?
}
var body: some View {
VStack {
AVPlayerControllerRepresented(player: player)
.edgesIgnoringSafeArea(.all)
.onAppear {
player.play()
}
.onDisappear {
player.pause()
player.seek(to: .zero)
}
}
.background(Color(.black))
.edgesIgnoringSafeArea(.all)
}
}
Run Code Online (Sandbox Code Playgroud)
解决后,如何更改 func playerDidFinishPlaying 中的视图?
我的应用程序有一个“HomeView”,它有三个按钮,单击时,它们会导航到一个将播放视频的新视图。在新视图的视频结束时,我想导航回此“HomeView”
import SwiftUI
struct ContentView: View {
var body: some View {
let width: CGFloat = 400
let height: CGFloat = 400
let txtWidth: CGFloat = 300
let txtHeight: CGFloat = 100
NavigationView {
ZStack {
Image("app_bg3")
.resizable()
.edgesIgnoringSafeArea(.all)
VStack {
ZStack {
NavigationLink(destination: ContentViewC()) {
HStack(alignment: .bottom) {
Spacer()
VStack {
VStack {
Image("OneCirclePlayBtn")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: width, height: height)
Text("The")
.font(Font.custom("Nunito-Regular", size: 43))
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(Color(.white))
.frame(width: txtWidth, height: txtHeight, alignment: .center)
Text("Voice")
.font(Font.custom("Nunito-Regular", size: 43))
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(Color(.white))
.frame(width: txtWidth, height: txtHeight, alignment: .center)
.offset(y: -50)
}
}
Spacer()
}
}
}.offset(y: 100)
HStack(spacing: 350) {
NavigationLink(destination: ContentViewA()) {
VStack {
VStack {
Image("TwoCirclePlayBtn")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: width, height: height)
Text("The Cast")
.font(Font.custom("Nunito-Regular", size: 33))
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(Color(.white))
.frame(width: txtWidth, height: txtHeight, alignment: .center)
}
}
}
NavigationLink(destination: ContentViewB()) {
VStack {
VStack {
Image("ThreeCirclePlayBtn")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: width, height: height, alignment: .center)
Text("The Artist")
.font(Font.custom("Nunito-Regular", size: 33))
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(Color(.white))
.frame(width: txtWidth, height: txtHeight, alignment: .center)
}
}
}
}.offset(y: -150)
}
}
}.navigationViewStyle(StackNavigationViewStyle())
.accentColor(.white)
.statusBar(hidden: true)
.background(StatusBarHideHelperView())
}
}
class StatusBarHideHelper: UIViewController {
override var prefersStatusBarHidden: Bool { true } // << important !!
}
struct StatusBarHideHelperView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
StatusBarHideHelper()
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
}
}
Run Code Online (Sandbox Code Playgroud)
class PlayerViewModel : ObservableObject {
@Published var videoDone = false
let player = AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: "Early Riser", ofType: "mp4")!))
private var cancellables = Set<AnyCancellable>()
init() {
NotificationCenter.default.publisher(for: .AVPlayerItemDidPlayToEndTime)
.sink { (_) in
self.videoDone = true
print("Video done")
DispatchQueue.main.async {
self.videoDone = false //reset it on the next run loop
}
}.store(in: &cancellables)
}
}
struct PlayerContentView: View {
@ObservedObject var viewModel = PlayerViewModel()
var body: some View {
VStack {
AVPlayerControllerRepresented(player: viewModel.player)
.edgesIgnoringSafeArea(.all)
.onAppear {
viewModel.player.play()
}
.onDisappear {
viewModel.player.pause()
viewModel.player.seek(to: .zero)
}
if viewModel.videoDone {
NavigationLink(destination: DetailView(), isActive: $viewModel.videoDone) {
EmptyView()
}
}
}
.background(Color(.black))
.edgesIgnoringSafeArea(.all)
}
}
struct DetailView : View {
var body: some View {
Text("Detail")
}
}
struct ContentView: View {
var body: some View {
NavigationView {
PlayerContentView()
}.navigationViewStyle(StackNavigationViewStyle())
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里假设您想使用 a 进行导航NavigationView,但如果情况并非如此,我可以编辑答案。
这里发生了什么:
我将播放器及其“完成”状态移至ObservableObject- 这样,我可以更好地控制如何处理通知。
收到AVPlayerItemDidPlayToEndTime通知后,我设置videoDone为 true
当为 true 时,我在视图层次结构中videoDone渲染 a ,并将其设置为NavigationLinkisActivevideoDone
请注意,如果您的视图未嵌入NavigationView(请参阅我的ContentView)中,则这将不起作用 -NavigationLink如果它存在于该层次结构之外,则不会执行任何操作。
更新:如果您想返回而不是新视图,则可以使用以下方法presentationMode(与之前相同的 PlayerViewModel):
struct PlayerContentView: View {
@ObservedObject var viewModel = PlayerViewModel()
@Environment(\.presentationMode) private var presentationMode: Binding<PresentationMode>
var body: some View {
VStack {
AVPlayerControllerRepresented(player: viewModel.player)
.edgesIgnoringSafeArea(.all)
.onAppear {
viewModel.player.play()
}
.onDisappear {
viewModel.player.pause()
viewModel.player.seek(to: .zero)
}
}
.background(Color(.black))
.edgesIgnoringSafeArea(.all)
.onReceive(viewModel.$videoDone) { (videoDone) in
if videoDone {
presentationMode.wrappedValue.dismiss()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1960 次 |
| 最近记录: |