5

Class A provides a string value. Class B has two members of A type inside itself, and provide a computed property "v" to choose 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 it works. Since both the A and B have a member "value", I make it a protocol like this:

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 

It works again!

Is this a bug of Swift, or something special for the property of protocols?

1 Answer 1

11

You have to 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 the new value to the object referenced by v1 if v1 != nil, and to the object referenced by v2 otherwise).

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

Your initial code example works because there the v property has the type A which is a reference type.

And your workaround

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

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

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.