不能在属性初始值设定项中使用实例成员“videoName";属性初始值设定项在 'self' 可用之前运行 [英] Cannot use instance member 'videoName' within property initializer; property initializers run before 'self' is available
问题描述
我对 SwiftUI 很陌生,当我尝试使用 Model 中的 videoName 显示视频时遇到了这个问题.在 player = AVPlayer(...)(第 4 行)中,我想使用 Model 中的 videoName,而不是通过字符串squats"查找资源.如果我更换它们,我会收到错误
I'm quite new to SwiftUI and I'm running into this problem as I'm trying to display a video using videoName from Model. In the player = AVPlayer(...)(line 4), instead of finding the resource by the string "squats", I want to use videoName from Model. If I replace them I get the error
不能在属性初始值设定项中使用实例成员videoName";属性初始值设定项在 'self' 可用之前运行
Cannot use instance member 'videoName' within property initializer; property initializers run before 'self' is available
有人可以帮我吗?
这是我的代码:
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>) {
}
}
}
推荐答案
选项 1:
为您的 View
创建一个初始化程序,用于创建您的 @State
初始值:
Option 1:
Create an initializer for your View
that creates your @State
initial value:
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
,这对于性能来说通常是一个非常糟糕的主意.
The downside to this is if ExercisingSessionView
gets initialized often (even if it doesn't get actually re-rendered to the view hierarchy), you're doing heavy lifting inside init
, which is generally a pretty bad idea for performance.
将 player
声明为可选并在 onAppear
中加载初始值:
Declare player
as optional and load the initial value in 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
只会被调用一次.
This avoids the issue in option 1 because onAppear
will only be called once.
请注意,在这里,我将 CustomVideoPlayer
内的 player
设置为常规的非绑定属性——因为 AVPlayer
是一个类,通过引用传递,没有理由使用 @Binding
.
Note that here, I've made player
inside CustomVideoPlayer
a regular, non-binding property -- because AVPlayer
is an class, passed by reference, there's no reason to have a @Binding
with it.
这篇关于不能在属性初始值设定项中使用实例成员“videoName";属性初始值设定项在 'self' 可用之前运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!