I am using swift 2.0, I have a protocol and an extension on the protocol to create a default implementation of a method, the code is as fallows:
protocol ColorImpressionableProtocol { var lightAccentColor: UIColor? {get set} var accentColor: UIColor? {get set} var darkAccentColor: UIColor? {get set} var specialTextColor: UIColor? {get set} mutating func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?) } extension ColorImpressionableProtocol { mutating func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?){ lightAccentColor = impresion?.lightAccentColor accentColor = impresion?.accentColor darkAccentColor = impresion?.darkAccentColor specialTextColor = impresion?.specialTextColor } }
I am later on in my code trying to call this method and am getting an error that reads:
"cannot use mutating member on immutable value:'self' is immutable"
The code is as fallows:
init(impresion: ColorImpressionableProtocol?){ super.init(nibName: nil, bundle: nil) adoptColorsFromImpresion(impresion) }
The only thing I can think of is that 'Self' in this case is a protocol, not a class. However I have to be missing something to make this concept work, A default implementation of a method defined by a protocol that edits values also defined by the same protocol.
Thank you for your help and time :)
What can a mutating function do? Essentially, a function that's been marked as mutating can change any property within its enclosing value. The word “value” is really key here, since Swift's concept of structured mutations only applies to value types, not to reference types like classes and actors.
Protocols let you describe what methods something should have, but don't provide the code inside. Extensions let you provide the code inside your methods, but only affect one data type – you can't add the method to lots of types at the same time.
The mutating keyword lets callers know that the method is going to make the value change. The best way to conceptualize this is to think of your struct the same as you would a number: if you perform the operation 4 + 1, 4 doesn't become 5, you've just gotten a new value after performing the operation.
Swift 4 allows multiple protocols to be called at once with the help of protocol composition.
If you intend to use the protocol only for classes then you can make it a class protocol (and remove the mutating
keyword):
protocol ColorImpressionableProtocol : class { // ... func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?) }
Then
init(impresion: ColorImpressionableProtocol?){ super.init(nibName: nil, bundle: nil) adoptColorsFromImpresion(impresion) }
compiles without problems.
You are adopting this protocol in a class so the self (which is reference type) is immutable. The compiler expects self to be mutable because of the mutable method declared in protocol. That's the reason you are getting this error.
The possible solutions are :
1) Implement a non mutating version of the method where the protocol being adopted. ie: implement the method in adopting class instead as a protocol extension.
class MyClass : ColorImpressionableProtocol { func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?){ lightAccentColor = impresion?.lightAccentColor accentColor = impresion?.accentColor darkAccentColor = impresion?.darkAccentColor specialTextColor = impresion?.specialTextColor } }
2) Make the protocol as class only protocol. This way we can remove the mutating keyword. It's the easiest solution but it can be only used in class.
To make protocol class only :
protocol MyProtocolName : AnyObject { } OR protocol MyProtocolName : class { }
3) Make sure only value types adopt this protocol.This may not be useful in all scenarios.
Here is the detailed explanation and solution for this case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With