无法分配给属性:'self'在UIViewController中是不可变的可表示的



我有以下代码片段:

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,因为我需要从暂停函数访问它。我该怎么做?

您看到的错误是由于结构是值类型,并且它们上更改其属性的任何方法都需要标记为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。 您还应该研究Cordinator以获取UIViewControllerRepresentable- 您需要一些东西来充当您的AVPlayerViewControllerDelegate

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

选项 1:在启动器中执行此操作

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

选项3:如果你需要在生命周期内修改player1,那么你需要把它保存在一些外部实体中,比如ObservableObject,因为你player是View结构体,不能修改自己,实际上是编译器错误中所说的。

最新更新