swift 无法分配给属性:“self "在UIViewControllerRepresentable中不可变

2exbekwf  于 2023-10-15  发布在  Swift
关注(0)|答案(2)|浏览(122)

我有以下代码片段:

struct player : UIViewControllerRepresentable {
    
    var url : String
    var player1: AVPlayer
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<player>) -> AVPlayerViewController {
        let controller = AVPlayerViewController()
        player1 = AVPlayer(url: URL(string: url)!)
        controller.player = player1
        return controller
    }
    
    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<player>) {
    }
    
    func pause() {
        player1.pause()
    }
}

这给出了错误:
'无法分配给属性:“自我”是不可变的
我需要在makeUIViewController函数之外使用AVPlayer,因为我需要从pause函数访问它。我该怎么做?

xuo3flqw

xuo3flqw1#

您看到的错误是由于结构是值类型,并且任何更改其属性的方法都需要标记为mutating。不幸的是,您不能标记makeUIViewController,因为它是在UIViewControllerRepresentable协议中定义的,但有一个相当简单的解决方案。
你实际上只是使用url来构造一个AVPlayer--没有必要保留它。为你的结构体写一个初始化器,它接受一个url字符串并构造一个AVPlayer。我把AVPlayer设为可选的,因为URL(string: String)返回一个Optional URL(你可以想象不是所有的字符串都是有效的url)。下面的代码按预期工作:

struct Player: UIViewControllerRepresentable {

    var player1: AVPlayer?

    public init(url string: String) {
        guard let url = URL(string: string) else {
            self.player1 = nil
            return
        }
        self.player1 = AVPlayer(url: url)
    }

    func makeUIViewController(context: UIViewControllerRepresentableContext<Player>) -> AVPlayerViewController {
        let controller = AVPlayerViewController()
        controller.player = player1
        return controller
    }

    func updateUIViewController(_ uiViewController: AVPlayerViewController,
                                context: UIViewControllerRepresentableContext<Player>) {}

    func pause() {
        player1?.pause()
    }
}

附带说明:Swift中的所有类型名称(类,结构,枚举)都是大写的:你的结构应该被命名为Player而不是player。您还应该查看UIViewControllerRepresentableCordinator-您需要一些东西来充当您的AVPlayerViewControllerDelegate

bq9c1y66

bq9c1y662#

有几种可能性可供选择(实际上这不是一个完整的选项列表,但希望它会有所帮助)

**Option1:**在initailizer中执行

struct player : UIViewControllerRepresentable {

    private var url : String
    private var player1: AVPlayer

    init(url: String) {
        self.url = url
        self.player1 = AVPlayer(url: URL(string: url)!)
    }

    func makeUIViewController(context: UIViewControllerRepresentableContext<player>) -> AVPlayerViewController {
        let controller = AVPlayerViewController()
        controller.player = player1
        return controller
    }

    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<player>) {
    }
}

**选项2:**在第一次请求更新控制器时执行

struct player : UIViewControllerRepresentable {

    var url : String
    var player1: AVPlayer

    func makeUIViewController(context: UIViewControllerRepresentableContext<player>) -> AVPlayerViewController {
        return AVPlayerViewController()
    }

    func updateUIViewController(_ playerController: AVPlayerViewController, context: UIViewControllerRepresentableContext<player>) {
        if playerController.player == nil {
            playerController.player = AVPlayer(url: URL(string: url)!)
        }
    }
}

**Option3:**如果你需要在生存期内修改player1,那么你需要将它保存在某个外部实体中,比如ObservableObject,因为你的player是View struct,不能修改自己,实际上就是编译器错误中所说的。

相关问题