Swift:无法为协议属性赋值?

时间:2015-04-19 10:43:27

标签: ios swift properties swift-protocols

A类提供字符串值。 B类本身内部有两个A类成员,并提供计算属性" v"选择其中之一。

class A {
    var value: String

    init(value: String) {
        self.value = value
    }
}

class B {
    var v1: A?
    var v2: A = A(value: "2")

    private var v: A {
        return v1 ?? v2
    }

    var value: String {
        get {
            return v.value
        }
        set {
            v.value = newValue
        }
    }
}

这段代码很简单,很有效。既然A和B都有一个成员"值",我就把它做成这样的协议:

protocol ValueProvider {
    var value: String {get set}
}

class A: ValueProvider {
    var value: String

    init(value: String) {
        self.value = value
    }
}

class B: ValueProvider {
    var v1: ValueProvider?
    var v2: ValueProvider = A(value: "2")

    private var v: ValueProvider {
        return v1 ?? v2
    }

    var value: String {
        get {
            return v.value
        }
        set {
            v.value = newValue // Error: Cannot assign to the result of the expression
        }
    }
}

如果我更改以下代码

v.value = newValue

var v = self.v
v.value = newValue

再次有效!

这是Swift的错误,还是协议属性的特殊内容?

1 个答案:

答案 0 :(得分:11)

您必须将协议定义为class协议:

protocol ValueProvider : class {
    var value: String {get set}
}

然后

var value: String {
    get { return v.value }
    set { v.value = newValue }
}

按预期编译和工作(即将新值分配给 v1 v1 != nil引用的对象和对象 由v2引用,否则)。

vValueProvider类型的只读计算属性。 通过将协议定义为编译器知道的类协议 v引用类型,因此v.value 即使引用本身是常量,也可以修改属性。

您的初始代码示例有效,因为v属性具有 类型A,它是一种引用类型。

你的解决方法

set {
    var tmp = v1 ?? v2
    tmp.value = newValue
}

可以设置变量的(读写)属性 任何情况(值类型或引用类型)。