Reputation: 4263
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
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
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