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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift 2在协议扩展中使用变异函数时出错“无法在不可变值上使用变异成员:'self'是不可变的相关的知识,希望对你有一定的参考价值。

不知道这里发生了什么,这似乎应该是非常直接的。我有一个可变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
  }

}
答案

问题是,在协议中,您将函数标记为变异,如果要在结构上使用协议,则需要执行此操作。但是,传递给testFunc的self是不可变的(它是对类的实例的引用),这会使编译器瘫痪。如果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的状态中。

以上是关于Swift 2在协议扩展中使用变异函数时出错“无法在不可变值上使用变异成员:'self'是不可变的的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 Xcode 7.3.1 在我的 Swift 2 项目中检查带有“po”的变量 - 加载辅助函数时出错

无法在 Swift 2.3 中编译 Siri 扩展

在 Swift 中使用协议作为类型时出错

Swift 2.0:协议扩展:具有相同函数签名的两个协议编译错误

表正在变异,触发器/函数可能看不到它/ORA-04088: 执行触发器时出错

Swift 2:UITableViewDataSource 协议扩展