Stephan
Stephan

Reputation: 4263

Protocol: Cannot assign to 'X' in 'Y' in Swift

I just defined a very simple protocol and a a class using generics which can handle this protocol.

In the lines marked with error you will get the error: "Cannot assign to 'flag' in 'aObj'.

 protocol Flag {
    var flag: Bool {get set}
 }


 class TestFlag<T: Flag>  {

    func toggle(aObj: T) {

        if aObj.flag {
            aObj.flag = false;  // <--- error
        } else {
            aObj.flag = true;   // <--- error
        }
    }
 }

Do you have an idea why and what I have to change to fix it?

Upvotes: 6

Views: 1095

Answers (2)

manojlds
manojlds

Reputation: 301087

From the docs:

Function parameters are constants by default. Trying to change the value of a function parameter from within the body of that function results in a compile-time error. This means that you can’t change the value of a parameter by mistake.

In this case, you can add inout so that the toggle is persisted beyond your function call:

func toggle(inout aObj: T) {           
   if aObj.flag {
      aObj.flag = false;
   else {
      aObj.flag = true;
   }
}

You could have also done:

func toggle(var aObj: T) { 
}

but that might not achieve what you wanted.

Upvotes: 6

Stephan
Stephan

Reputation: 4263

manojlds answer is correct and therefore I accepted it.

Nevertheless there was a similar answer some days ago with the same solution but with a other argumentation (seems now deleted).

The argumentation was about that the compliler can not know if the protocol is used for a class, a struct or a enum. With Swift, protocols can by applied on all this types. But struct instances use a by-value call and for classes instances (objects) it us a by-reference call.

From my perspective this answer was correct too, because you can solve the problem with a 2nd solution:

@objc  
protocol Flag {
    var flag: Bool {get set} 
}

Just add the @obj attriute on the protocol. As a result you can use this protocol only for a class which lead to the result only by-refernece calls are allowd. Therefore the compiler don't need anymore the inout information.

But I searched for a solution to increase the reuse of the protocol and use now manojlds suggestions.

Upvotes: 2

Related Questions