不能在属性初始值设定项中使用实例成员“videoName";属性初始值设定项在 'self' 可用之前运行 [英] Cannot use instance member 'videoName' within property initializer; property initializers run before 'self' is available

查看:34
本文介绍了不能在属性初始值设定项中使用实例成员“videoName";属性初始值设定项在 'self' 可用之前运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆