Swift 2 Ошибка при использовании функции изменения в расширении протокола «Невозможно использовать изменяющийся член для неизменяемого значения: 'self' является неизменным

Не уверен, что здесь происходит, похоже, все должно быть довольно просто. У меня есть протокол, который изменяет var, расширение с функцией изменения. В testClass.testFunc дела идут плохо, когда я пытаюсь использовать mtkAnimQueAppend, объявленный в расширении, я получаю эту ошибку: «Невозможно использовать изменяющийся член в неизменяемом value: "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
  }

}

person Michael Kennedy    schedule 13.10.2015    source источник
comment
Я считаю эту проблему совершенно невероятной на нескольких уровнях. Самое первое, что вы хотите сделать со Swift, - это, конечно, создать миксин, который работает подобным образом, для контроллеров представления. Я имею в виду, что это язык, ориентированный на протокол. И ios - это контроллеры просмотра. Итак, что вы делаете в первую очередь? Для меня это невероятно, что (A) Apple не убрала это с самого начала, и (B) проблема настолько неясна. Повсюду должно быть 10 000 QA по этому поводу! Ах хорошо.   -  person Fattie    schedule 22.01.2017


Ответы (1)


Проблема в том, что в протоколе вы отмечаете функцию как изменяющуюся, что вам нужно сделать, если вы хотите использовать протокол в структуре. Однако самость, передаваемая в testFunc, является неизменной (это ссылка на экземпляр класса), и это сбивает компилятор с толку. Это имело бы смысл, если бы 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.

person JeremyP    schedule 13.10.2015
comment
О мой Бог. Я никогда этого не знал. Потрясающие! - person devxoul; 08.02.2016
comment
Я бы хотел, чтобы протокол класса был первым, что предложил Xcode. Спасибо за вашу помощь - person Aron; 26.02.2016