Swift: Failed to set value for protocol property?

Class A provides a string value. Class B has two members of type A inside itself and provides the computed property "v" to select one of them.

class A { var value: String init(value: String) { self.value = value } } class B { var v1: A? var v2: A = A(value: "2") private var v: A { return v1 ?? v2 } var value: String { get { return v.value } set { v.value = newValue } } } 

This code is simple and works. Since both values ​​A and B have a value of "value", I make it as follows:

 protocol ValueProvider { var value: String {get set} } class A: ValueProvider { var value: String init(value: String) { self.value = value } } class B: ValueProvider { var v1: ValueProvider? var v2: ValueProvider = A(value: "2") private var v: ValueProvider { return v1 ?? v2 } var value: String { get { return v.value } set { v.value = newValue // Error: Cannot assign to the result of the expression } } } 

If I change the following code

 v.value = newValue 

to

 var v = self.v v.value = newValue 

He is working again!

Is this a Swift bug or something special for a protocol property?

+5
source share
1 answer

You must define the protocol as a class protocol:

 protocol ValueProvider : class { var value: String {get set} } 

Then

 var value: String { get { return v.value } set { v.value = newValue } } 

compiles and works as expected (i.e. assigns a new value to the object referenced by v1 if v1 != nil , and to the object referenced by v2 otherwise).

v is a read- ValueProvider property of type ValueProvider . By defining a protocol as a class protocol, the compiler knows that v is a reference type, and therefore its v.value property can be changed, even if the link itself is a constant.

Your original code example works because the v property is of type A , which is a reference type.

And your workaround

 set { var tmp = v1 ?? v2 tmp.value = newValue } 

works because the properties of variables (read-write) can be set in anyway (value type or reference type).

+10
source

All Articles