Swift 2 Error using mutating function in Protocol extension "Cannot use mutating member on immutable value: 'self' is immutable

10,981

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:

  1. make the protocol class only

    protocol MTKAnimateValueDelegate: class { ...
    
  2. 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

  1. 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.

Share:
10,981

Related videos on Youtube

Michael Kennedy
Author by

Michael Kennedy

Updated on April 02, 2020

Comments

  • Michael Kennedy
    Michael Kennedy over 4 years

    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
      }
    
    }
    
    • Fattie
      Fattie over 7 years
      I find this whole issue quite incredible on a number of levels. The very first thing you want to do with Swift, is of course make a mixin that works like this, for view controllers. I mean it's a protocol oriented language. And ios "is view controllers". So what's the first thing you do? For me it's beyond belief that (A) Apple didn't tidy this from the getgo, and (B) the issue is so obscure. There should be 10,000 QA about this everywhere! Ah well.
  • devxoul
    devxoul over 8 years
    Oh my god. I never knew this. Awesome!
  • Aron
    Aron over 8 years
    I wish a class protocol was the first thing Xcode suggested. Thanks for your help