首页 > 解决方案 > 无法分配给属性:“self”在 UIViewControllerRepresentable 中是不可变的

问题描述

我有以下代码片段:

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()
    }
}

这给出了错误:

'不能分配给属性:'self' 是不可变的'

我需要在 makeUIViewController 函数之外拥有 AVPlayer,因为我需要从 pause 函数中访问它。我怎样才能做到这一点?

标签: swiftswiftui

解决方案


您看到的错误是由于结构是值类型,并且它们上的任何更改其属性的方法都需要标记为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 中的所有类型名称(类、结构、枚举)按照惯例都是大写的:你的结构应该被称为Playernot player。您还应该考虑Cordinator-UIViewControllerRepresentable您需要一些东西来充当您的AVPlayerViewControllerDelegate.


推荐阅读