web-dev-qa-db-fra.com

Swift 2 Erreur lors de l'utilisation de la fonction de mutation dans l'extension de protocole "Impossible d'utiliser le membre de mutation sur une valeur immuable: 'self' est immuable

Je ne sais pas ce qui se passe ici, cela semble être assez simple. J'ai un protocole qui var mutable, une extension avec une fonction de mutation. Les choses chutent dans le testClass.testFunc , lorsque j'essaie d'utiliser mtkAnimQueAppend déclaré dans l'extension, j'obtiens cette erreur: "Impossible d'utiliser un membre en mutation sur une valeur immuable: 'self' est immuable.

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
  }

}
45
Michael Kennedy

Le problème est que, dans le protocole, vous marquez la fonction comme étant en mutation, ce que vous devez faire si vous souhaitez utiliser le protocole sur une structure. Cependant, le self qui est passé à testFunc est immuable (c'est une référence à une instance de la classe) et qui déclenche le compilateur. Cela aurait du sens si testClass était en fait une structure et que vous pouviez faire muter la fonction pour résoudre le problème.

Je peux voir deux solutions:

  1. faire la classe de protocole uniquement

    protocol MTKAnimateValueDelegate: class { ...
    
  2. Faites de testClass une structure et marquez testFunc comme étant en mutation.

Quoi qu'il en soit, je pense que c'est un bug qui doit être signalé à Apple.

Modifier

  1. Une autre solution consiste à créer une copie modifiable de self
func testFunc() {
    var animValue = MTKAnimateValue(fromValue: 10, toValue: 20, inSeconds: 2)
    animValue.isAnimating = true
    var mutableSelf = self
    mutableSelf.mtkAnimQueAppend(animValue) 
  }

Puisque mutableSelf est une référence, tout changement apporté par la fonction de mutation sera toujours reflété dans l'état de self.

101
JeremyP