我有一个协议,仅描述一个接口。
protocol SampleProtocol {
var message: String? { get set }}
为什么编译器总是将符合的值/对象视为值类型?
示例示例,
// Protocol value usage
import Foundation
protocol SampleProtocol {
var message: String? { get set }
}
final class SampleObject: SampleProtocol {
var message: String?
}
final class Controller {
var sampleValue: SampleProtocol! {
didSet {
print("New value has been set")
}
}
}
let controller = Controller()
controller.sampleValue = AlphaObject() // Correctly prints "New value has been set"
controller.sampleValue.message = "New message" // Prints again "New value has been set", like for value types
它不会创建该对象的副本。在两个调用中,它是同一对象–如果将print(Unmanaged.passUnretained(sampleValue as AnyObject).toOpaque())
放入didSet中,您将看到地址相同。编译器不知道它在处理值类型还是引用类型。如果您将class关键字放在协议声明中,如下所示:
protocol SampleProtocol: class { ... }
didSet将被调用一次,因为编译器知道它是引用类型,因此不会重新分配引用。我猜生成的不同的setter取决于属性的类型
您的协议SampleProtocol
可以由class
或struct
采纳。 Swift会使用值类型的行为,该行为是限制性更强的类型,直到您告诉它该协议仅由class
引用类型使用。
将协议更改为此以获取引用类型的行为:
protocol SampleProtocol: class {
var message: String? { get set }
}
很好奇。 The Swift 5.1 Programming Guide - Class-Only Protocols建议使用AnyObject
编写它:
protocol SampleProtocol: AnyObject {
var message: String? { get set }
}
两者都做。