我有以下代码片段:
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结构体,不能修改自己,实际上是编译器错误中所说的。