不能在 属性 初始值设定项中使用实例成员 'videoName'; 属性 初始值设定项 运行 在 'self' 可用之前
Cannot use instance member 'videoName' within property initializer; property initializers run before 'self' is available
我是 SwiftUI 的新手,我 运行 遇到了这个问题,因为我正在尝试使用 Model 中的 videoName 显示视频。
在 player = AVPlayer(...)(第 4 行)中,我不想通过字符串“squats”查找资源,而是想使用 Model 中的 videoName。如果我更换它们,我会得到错误
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
初始值:
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
中做着繁重的工作,这通常对性能来说是一个非常糟糕的主意。
选项 2:
声明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
只会被调用一次。
请注意,在这里,我在 CustomVideoPlayer
中制作了 player
一个常规的、非绑定的 属性 -- 因为 AVPlayer
是一个 class ,通过引用传递,没有理由使用 @Binding
。
您可以将您的名字传递给您的自定义视图。
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
}
}
当您将 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")!))
}
请记住,您必须添加
我是 SwiftUI 的新手,我 运行 遇到了这个问题,因为我正在尝试使用 Model 中的 videoName 显示视频。 在 player = AVPlayer(...)(第 4 行)中,我不想通过字符串“squats”查找资源,而是想使用 Model 中的 videoName。如果我更换它们,我会得到错误
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
初始值:
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
中做着繁重的工作,这通常对性能来说是一个非常糟糕的主意。
选项 2:
声明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
只会被调用一次。
请注意,在这里,我在 CustomVideoPlayer
中制作了 player
一个常规的、非绑定的 属性 -- 因为 AVPlayer
是一个 class ,通过引用传递,没有理由使用 @Binding
。
您可以将您的名字传递给您的自定义视图。
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
}
}
当您将 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")!))
}
请记住,您必须添加