【问题标题】:Protocol Extension, Mutating Function协议扩展,变异函数
【发布时间】:2015-12-05 23:08:30
【问题描述】:

我使用的是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)
}

我唯一能想到的是,在这种情况下,“Self”是一个协议,而不是一个类。但是我必须遗漏一些东西才能使这个概念发挥作用,由协议定义的方法的默认实现,该协议编辑也由同一协议定义的值。

感谢您的帮助和时间:)

【问题讨论】:

    标签: ios iphone swift protocols ios9


    【解决方案1】:

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

    可能的解决方案是:

    1) 实现协议所在方法的非变异版本 被采纳。即:实现采用类的方法,而不是作为 协议扩展。

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

    2) 将协议设为仅类协议。这样我们可以删除 mutating 关键字。这是最简单的解决方案,但只能在课堂上使用。

    仅制作协议类:

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

    3) 确保只有值类型采用此协议。这在 所有场景。

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

    【讨论】:

      【解决方案2】:

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

      protocol ColorImpressionableProtocol : class {
      
          // ...
      
          func adoptColorsFromImpresion(impresion: ColorImpressionableProtocol?)
      }
      

      然后

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

      编译没有问题。

      【讨论】:

      • 我相信这是我正在尝试做的正确语法,Perfecto!谢谢
      • 为了理智,我不得不问这个问题......除了类之外还有什么可以实现协议,那是为了防止什么?我只是没有看到任何其他结果,而是符合它的类
      • @CWineland:协议也可以通过结构实现。
      猜你喜欢
      • 2016-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多