Search code examples
swiftswift-protocolslet

Can we edit properties of "let" protocol properties in Swift?


I have a code like this (play in a playground:

protocol ServiceProtocol {
    var enabled: Bool { get set }
}

class Service: ServiceProtocol {
    var enabled: Bool = false
}

class A {
    let service = Service()
}

class B {
    let service: ServiceProtocol = Service()
}

let a = A()
let b = B()

a.service.enabled = false
b.service.enabled = false // <-- the error is here: Cannot assign to property: 'service' is a 'let' constant

If I reference service as a Service (class A), everything works as expected. In class B, with service being a ServiceProtocol, I have the error:

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

It is a nonsense to me, as I am not trying to assign anything to service: I am only trying to assign a property of service. enabled being get set, I should be able to assign it, like in A.

If I declare service as a var in class B, the error disappears.

Any ideas?


Solution

  • This is because classes, structs and enums can implement your protocol so the compiler doesn't know if it is a reference type or value type. You can restrict your protocol to be for only classes and your code will work

    protocol ServiceProtocol: AnyObject {
        var enabled: Bool { get set }
    }
    

    And now

    b.service.enabled = false
    

    compiles fine