Swift 2在协议扩展中使用变异函数时出错“无法在不可变值上使用变异成员:'self'是不可变的

时间:2015-10-13 09:23:43

标签: protocols swift2 ios9 swift-extensions swift-protocols

不确定这里发生了什么,这似乎应该是非常直接的。我有一个可变var的协议,一个带有变异函数的扩展。事情正在 testClass.testFunc 中出现,当我尝试使用扩展中声明的 mtkAnimQueAppend 时,我收到此错误:“不能在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 个答案:

答案 0 :(得分:101)

问题在于,在协议中将函数标记为变异,如果要在结构上使用协议,则需要执行此操作。但是,传递给testFunc的self是不可变的(它是对类实例的引用)并且正在使编译器跳闸。如果testClass实际上是一个结构,那么这将是有意义的,你可以让函数变异来解决问题。

我可以看到两种解决方法:

  1. 仅制作协议类

    protocol MTKAnimateValueDelegate: class { ...
    
  2. 使testClass成为一个结构,并将testFunc标记为变异。

  3. 无论哪种方式,我认为这是一个需要向Apple报告的错误。

    修改

    1. 另一种方法是制作self
    2. 的可变副本
      func testFunc() {
          var animValue = MTKAnimateValue(fromValue: 10, toValue: 20, inSeconds: 2)
          animValue.isAnimating = true
          var mutableSelf = self
          mutableSelf.mtkAnimQueAppend(animValue) 
        }
      

      由于mutableSelf是一个引用,变异函数所做的任何更改仍会反映在self的状态中。