协议扩展,变异功能

Protocol Extension, Mutating Function

我正在使用 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
    }
}

稍后我在我的代码中尝试调用此方法并收到错误消息:

"cannot use mutating member on immutable value:'self' is immutable"

代码如下:

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

我唯一能想到的是 'Self' 在这种情况下是一个协议,而不是 class。但是我必须缺少一些东西才能使这个概念起作用,一个由协议定义的方法的默认实现,该协议编辑也由相同协议定义的值。

感谢您的帮助和时间:)

如果您打算仅将协议用于 classes 那么您可以 它是一个 class 协议(并删除 mutating 关键字):

protocol ColorImpressionableProtocol : class {

    // ...

    func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?)
}

然后

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

编译没有问题。

您在 class 中采用此协议,因此 self(引用类型)是不可变的。由于协议中声明的可变方法,编译器期望 self 是可变的。这就是您收到此错误的原因。

可能的解决方案是:

1) Implement a non mutating version of the method where the protocol being adopted. ie: implement the method in adopting class instead as a protocol extension.

class MyClass : ColorImpressionableProtocol {

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

2) Make the protocol as class only protocol. This way we can remove the mutating keyword. It's the easiest solution but it can be only used in class.

仅制定协议 class :

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

3) Make sure only value types adopt this protocol.This may not be useful in all scenarios.

Here就是这个案例的详细解释和解决方法