lychee
lychee

Reputation: 1851

Cannot assign to a property: 'class' is a 'let' constant

I'm trying to update a property on a service that is defined as let subscriber: SubscriberContextProviding in the WatchlistViewModel by simply setting it directly like so:

subscriber.watchlist = watchlist 

relevant subscriber definition:

final class Subscriber: SubscriberContextProviding {
  var watchlist = [String]()
}

however I get an error saying: Cannot assign to property: 'subscriber' is a 'let' constant . The subscriber service is declared as a let and is initialised in the client init. here is the relevant protocol part & init.

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

class WatchlistViewModel: NSObject {
  let subscriber: SubscriberContextProviding

  init(subscriber: SubscriberContextProviding){
    self.subscriber = subscriber
    super.init()
  }
}

however If I change the protocol from the one above to

protocol SubscriberContextProviding {
  func set(watchlist: [String])
}

and I simply define the function in the subscriber as

func set(watchlist: [String]){
  self.watchlist = watchlist
}

and instead of setting the property directly now using the function like so

subscriber.set(watchlist: watchlist)

works no problem. Why the first approach doesn't work while the latter one does as the result is the same of both approaches?

Upvotes: 2

Views: 2083

Answers (2)

Alexander
Alexander

Reputation: 63167

The "issue" (though it's not an issue, really) is that you haven't restricted SubscriberContextProviding to being a class-bound protocol (with : AnyObject).

let subscriber: SubscriberContextProviding is declaring that your subscriber variable with contain an existential of any object whose type conforms to SubscriberContextProviding. Since that protocol isn't class-bound, it's possible that the concrete value you're dealing with is a value type (tuple, struct or enum), for which mutations are only allowed on mutable var variables. This existential is itself a value type, and abides the same rules of only allowing mutations on var variables.

Thus, you must either:

  1. Declare SubscriberContextProviding as class-bound:

    protocol SubscriberContextProviding: AnyObject { ... }
    

    or

  2. Keep your protocol as-is, but make your subscriber variable mutable, to account for the possibility that it contains a value type.

Upvotes: 7

Alain Bianchini
Alain Bianchini

Reputation: 4171

Add this to your protocol:

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

Upvotes: 1

Related Questions