我对 SwiftUI 很陌生,当我尝试使用 Model 中的 videoName 显示视频时遇到了这个问题。 在 player = AVPlayer(...)(第 4 行)中,我想使用 Model 中的 videoName,而不是通过字符串“squats”查找资源。如果我更换它们,我会收到错误
<块引用>不能在属性初始值设定项中使用实例成员“videoName”;属性初始值设定项在 'self' 可用之前运行
有人可以帮我吗?
这是我的代码:
struct ExercisingSessionView: View {
let exerciseName: String
let videoName: String
@State var player = AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: "squats", ofType: "mov")!))
@State var isplaying = false
@State var showcontrols = false
var body: some View {
CustomVideoPlayer(player: $player)
.frame(width: 390, height: 219)
.onTapGesture {
self.showcontrols = true
}
}
struct CustomVideoPlayer : UIViewControllerRepresentable {
@Binding var player: AVPlayer
func makeUIViewController(context: UIViewControllerRepresentableContext<CustomVideoPlayer>) -> AVPlayerViewController {
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<CustomVideoPlayer>) {
}
}
}
答案 0 :(得分:0)
为您的 View
创建一个初始化程序,用于创建您的 @State
初始值:
struct ExercisingSessionView: View {
let exerciseName: String
let videoName: String
@State var player : AVPlayer
@State var isplaying = false
@State var showcontrols = false
init(exerciseName: String, videoName: String) {
self.exerciseName = exerciseName
self.videoName = videoName
self._player = State(initialValue: AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: videoName, ofType: "mov")!)))
}
var body: some View {
CustomVideoPlayer(player: $player)
.frame(width: 390, height: 219)
.onTapGesture {
self.showcontrols = true
}
}
}
这样做的缺点是,如果 ExercisingSessionView
经常被初始化(即使它实际上没有被重新渲染到视图层次结构中),你在 init
内部做了繁重的工作,这是对于性能来说,这通常是一个非常糟糕的主意。
将 player
声明为可选并在 onAppear
中加载初始值:
struct ExercisingSessionView: View {
let exerciseName: String
let videoName: String
@State var player : AVPlayer?
@State var isplaying = false
@State var showcontrols = false
var body: some View {
Group {
if let player = player {
CustomVideoPlayer(player: player)
.frame(width: 390, height: 219)
.onTapGesture {
self.showcontrols = true
}
}
}.onAppear {
player = AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: videoName, ofType: "mov")!))
}
}
}
struct CustomVideoPlayer : UIViewControllerRepresentable {
var player: AVPlayer
func makeUIViewController(context: UIViewControllerRepresentableContext<CustomVideoPlayer>) -> AVPlayerViewController {
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<CustomVideoPlayer>) {
}
}
这避免了选项 1 中的问题,因为 onAppear
只会被调用一次。
请注意,在这里,我将 player
内的 CustomVideoPlayer
设为常规的非绑定属性——因为 AVPlayer
是一个类,通过引用传递,因此没有理由拥有一个@Binding
。
答案 1 :(得分:0)
您可以将您的名字传递给您的自定义视图。
struct ExercisingSessionView: View {
let exerciseName: String
let videoName: String
@State var isplaying = false
@State var showcontrols = false
var body: some View {
CustomVideoPlayer(player: videoName)
.frame(width: 390, height: 219)
.onTapGesture {
self.showcontrols = true
}
}
struct CustomVideoPlayer : UIViewControllerRepresentable {
let videoName: String
func makeUIViewController(context: UIViewControllerRepresentableContext<CustomVideoPlayer>) -> AVPlayerViewController {
let controller = AVPlayerViewController()
controller.player = AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: videoName, ofType: "mov")!))
controller.showsPlaybackControls = false
return controller
}
}
答案 2 :(得分:0)
我假设错误发生在这一行,当您将 squats
替换为 videoName
时:
@State var player = AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: "squats", ofType: "mov")!))
您收到错误的原因是当您调用这行代码时未定义 videoName
。
要解决此问题,您可以在您定义的自定义 init
方法中设置您的属性。像这样:
let videoName: String
@State var player: AVPlayer
init(exerciseName: String, videoName: String) {
self.exerciseName = exerciseName
self.videoName = videoName
self.player = AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forResource: videoName, ofType: "mov")!))
}
请记住,您必须添加