无法分配给属性:“self”在 UIViewControllerRepresentable 中是不可变的
Posted
技术标签:
【中文标题】无法分配给属性:“self”在 UIViewControllerRepresentable 中是不可变的【英文标题】:Cannot assign to property: 'self' is immutable in UIViewControllerRepresentable 【发布时间】:2019-11-25 17:18:51 【问题描述】:我有以下代码sn-p:
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 函数中访问它。我该怎么做?
【问题讨论】:
【参考方案1】:您看到的错误是由于结构是值类型,并且它们上的任何更改其属性的方法都需要标记为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
。
【讨论】:
【参考方案2】:有几种可能可供选择(实际上它不是一个完整的选项列表,但希望它会有所帮助)
选项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 结构,不能自行修改,实际上是编译器错误中所说的。
【讨论】:
以上是关于无法分配给属性:“self”在 UIViewControllerRepresentable 中是不可变的的主要内容,如果未能解决你的问题,请参考以下文章