问题
Not sure what's going on here, this seems like it should be pretty straight forward. I have a protocol that mutable var, an extension with a mutating function. Things are crapping out in the testClass.testFunc, when I try and use mtkAnimQueAppend declared in the extension, I get this error: "Cannot use mutating member on immutable value: 'self' is immutable.
protocol MTKAnimateValueDelegate {
var mtkAnimQue:[MTKAnimateValue]? {get set}
}
extension MTKAnimateValueDelegate {
///Adds element to que
mutating func mtkAnimQueAppend(element:MTKAnimateValue) {
if mtkAnimQue != nil {
mtkAnimQue?.append(element)
} else {
mtkAnimQue = [element]
}
}
}
class testClass: MTKAnimateValueDelegate {
var mtkAnimQue:[MTKAnimateValue]?
func testFunc() {
var animValue = MTKAnimateValue(fromValue: 10, toValue: 20, inSeconds: 2)
animValue.isAnimating = true
mtkAnimQueAppend(animValue) //ERROR: "Cannot use mutating member on immutable value: 'self' is immutable
}
}
回答1:
The problem is that, in the protocol you mark the function as mutating, which you need to do if you want to use the protocol on a struct. However, the self that is passed to testFunc
is immutable (it's a reference to a instance of the class) and that is tripping up the compiler. This would make sense if testClass was actually a struct and you could make the function mutating to resolve the issue.
I can see two work arounds:
make the protocol class only
protocol MTKAnimateValueDelegate: class { ...
Make testClass a struct and mark testFunc as mutating.
Either way, I think this is a bug that needs to be reported to Apple.
Edit
- Another way around it is to make a mutable copy of
self
func testFunc() {
var animValue = MTKAnimateValue(fromValue: 10, toValue: 20, inSeconds: 2)
animValue.isAnimating = true
var mutableSelf = self
mutableSelf.mtkAnimQueAppend(animValue)
}
Since mutableSelf
is a reference, any changes the mutating function makes will still be reflected in self
's state.
来源:https://stackoverflow.com/questions/33098884/swift-2-error-using-mutating-function-in-protocol-extension-cannot-use-mutating