web-dev-qa-db-ja.com

Swift 2プロトコル拡張での変更関数の使用エラー "不変値での変更メンバーの使用はできません: 'self'は不変です

ここで何が起こっているのかわかりませんが、これはかなり簡単なはずです。可変関数、可変機能を備えた拡張機能を備えたプロトコルがあります。拡張機能で宣言されたmtkAnimQueAppendを使用しようとすると、testClass.testFuncで問題が発生します。このエラーが発生します。 "不変の値には変更メンバーを使用できません: '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
  }

}
45
Michael Kennedy

問題は、プロトコルで関数をミューティングとしてマークすることです。これは、構造体でプロトコルを使用する場合に行う必要があります。ただし、testFuncに渡されるselfは不変(クラスのインスタンスへの参照)であり、コンパイラーを起動します。これは、testClassが実際に構造体であり、関数を変更して問題を解決できる場合に意味があります。

私は2つの回避策を見ることができます:

  1. プロトコルクラスのみを作成する

    protocol MTKAnimateValueDelegate: class { ...
    
  2. TestClassを構造体にし、testFuncを変更可能としてマークします。

いずれにせよ、これはアップルに報告する必要があるバグだと思います。

編集

  1. 別の方法は、selfの可変コピーを作成することです
func testFunc() {
    var animValue = MTKAnimateValue(fromValue: 10, toValue: 20, inSeconds: 2)
    animValue.isAnimating = true
    var mutableSelf = self
    mutableSelf.mtkAnimQueAppend(animValue) 
  }

mutableSelfは参照であるため、変更関数による変更はすべてselfの状態に反映されます。

101
JeremyP