46

不知道这里发生了什么,这似乎应该很简单。我有一个可变 var 的协议,一个具有变异功能的扩展。testClass.testFunc中的事情正在崩溃,当我尝试使用扩展中声明的mtkAnimQueAppend时,我收到此错误:“不能在不可变值上使用变异成员:'self' 是不可变的。

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
  }

}
4

1 回答 1

105

问题是,在协议中,您将函数标记为变异,如果您想在结构上使用协议,则需要这样做。但是,传递给的 selftestFunc是不可变的(它是对类实例的引用),这会使编译器出错。如果 testClass 实际上是一个结构,那么这将是有意义的,并且您可以使函数发生变异以解决问题。

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

  1. 只制作协议类

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

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

编辑

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

由于mutableSelf是参考,变异函数所做的任何更改仍将反映在self的状态中。

于 2015-10-13T09:40:37.413 回答