无法分配给属性:“class”是“let”常量

kod*_*r16 2 swift swift-protocols

let subscriber: SubscriberContextProviding我正在尝试通过简单地直接设置来更新定义为的服务的属性,WatchlistViewModel如下所示:

subscriber.watchlist = watchlist 
Run Code Online (Sandbox Code Playgroud)

相关订户定义:

final class Subscriber: SubscriberContextProviding {
  var watchlist = [String]()
}
Run Code Online (Sandbox Code Playgroud)

但是我收到一条错误消息:Cannot assign to property: 'subscriber' is a 'let' constant 。订阅者服务被声明为 alet并在客户端中初始化init。这是相关的协议部分 & init

protocol SubscriberContextProviding {
  var watchlist: [String] { get set }
}

class WatchlistViewModel: NSObject {
  let subscriber: SubscriberContextProviding

  init(subscriber: SubscriberContextProviding){
    self.subscriber = subscriber
    super.init()
  }
}
Run Code Online (Sandbox Code Playgroud)

但是如果我将协议从上面的协议更改为

protocol SubscriberContextProviding {
  func set(watchlist: [String])
}
Run Code Online (Sandbox Code Playgroud)

我只是将函数定义subscriber

func set(watchlist: [String]){
  self.watchlist = watchlist
}
Run Code Online (Sandbox Code Playgroud)

而不是现在使用像这样的函数直接设置属性

subscriber.set(watchlist: watchlist)
Run Code Online (Sandbox Code Playgroud)

工作没问题。为什么第一种方法不起作用,而后一种方法却有效,因为两种方法的结果相同?

Ale*_*ica 6

“问题”(尽管这实际上不是问题)是您没有限制SubscriberContextProviding为类绑定协议(使用: AnyObject)。

let subscriber: SubscriberContextProviding声明您的subscriber变量包含类型符合 的任何对象的存在性SubscriberContextProviding。由于该协议不受类限制,因此您正在处理的具体值可能是值类型(元组、结构或枚举),仅允许在可变var变量上进行突变。这种存在本身就是一种值类型,并且遵守仅允许变量发生突变的相同规则var

因此,您必须:

  1. 声明SubscriberContextProviding为类绑定:

    protocol SubscriberContextProviding: AnyObject { ... }
    
    Run Code Online (Sandbox Code Playgroud)

    或者

  2. 保持协议不变,但使subscriber变量可变,以考虑它包含值类型的可能性。