Подтвердить что ты не робот

Расширение протокола, функция Mutating

Я использую swift 2.0, у меня есть протокол и расширение в протоколе, чтобы создать стандартную реализацию метода, код как паров:

protocol ColorImpressionableProtocol {

    var lightAccentColor: UIColor? {get set}
    var accentColor: UIColor? {get set}
    var darkAccentColor: UIColor? {get set}
    var specialTextColor: UIColor? {get set}

    mutating func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?)
}

extension ColorImpressionableProtocol {

    mutating func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?){
        lightAccentColor = impresion?.lightAccentColor
        accentColor = impresion?.accentColor
        darkAccentColor = impresion?.darkAccentColor
        specialTextColor = impresion?.specialTextColor
    }
}

Позднее в моем коде пытается вызвать этот метод, и я получаю сообщение об ошибке:

"не может использовать мутирующий элемент в неизменяемом значении:" self "неизменен"

Код является парой:

init(impresion: ColorImpressionableProtocol?){
        super.init(nibName: nil, bundle: nil)
        adoptColorsFromImpresion(impresion)
}

Единственное, что я могу придумать, это то, что "Я" в этом случае является протоколом, а не классом. Однако мне нужно что-то упустить, чтобы эта концепция работала. Реализация по умолчанию метода, определенного протоколом, который редактирует значения, также определенные одним и тем же протоколом.

Спасибо за помощь и время:)

4b9b3361

Ответ 1

Если вы собираетесь использовать протокол только для классов, вы можете сделать это протокол класса (и удалить ключевое слово mutating):

protocol ColorImpressionableProtocol : class {

    // ...

    func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?)
}

Тогда

init(impresion: ColorImpressionableProtocol?){
    super.init(nibName: nil, bundle: nil)
    adoptColorsFromImpresion(impresion)
}

компилируется без проблем.

Ответ 2

Вы принимаете этот протокол в классе, так что self (который является ссылочным типом) является неизменным. Компилятор ожидает, что self будет изменяемым с помощью изменяемого метода, объявленного в протоколе. Вот почему вы получаете эту ошибку.

Возможные решения:

1) Реализовать немутирующую версию метода, где протокол принимаются то есть: реализовать метод в принятии класса вместо расширение протокола.

class MyClass : ColorImpressionableProtocol {

   func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?){
        lightAccentColor = impresion?.lightAccentColor
        accentColor = impresion?.accentColor
        darkAccentColor = impresion?.darkAccentColor
        specialTextColor = impresion?.specialTextColor
    }
}

2) Сделать протокол как протокол только для класса. Таким образом, мы можем удалить мутационное ключевое слово. Это самое простое решение, но его можно использовать только в классе.

Чтобы сделать класс протокола только:

protocol MyProtocolName : AnyObject { }
OR
protocol MyProtocolName : class { }

3) Убедитесь, что только типы значений принимают этот протокол. Это может быть бесполезно в все сценарии.

Здесь - подробное объяснение и решение для этого случая.