关联类型为 class 的协议的扩展?
Extension of a protocol where the associatedType is class?
我试过这样的事情:
protocol MyModelProtocol {
var name: String { get set }
}
protocol MyProtocol {
associatedtype Model: MyModelProtocol
func changeModel(_ model: Model)
}
extension MyProtocol where Model: AnyObject {
}
编译器很高兴。但是,在这个扩展中,编译器仍然不确定 Model 是 class 还是 struct。示例:
extension MyProtocol where Model: AnyObject {
func changeModel(_ model: Model) {
model.name = "changed"
}
}
因此,我得到错误:"Cannot assign to property: 'model' is a 'let' constant"
我如何告诉编译器在该协议扩展中关联的类型将始终是 class?
顺便说一句,这只是一个简短的例子。我知道我可以在这种情况下使用 inout 参数,但它对我不起作用,因为我想像这样更改异步回调内部的对象:
func changeModel(_ model: inout Model, completion: @escaping () -> Void) {
Api.shared.doRandomAsyncStuff() { (_) in
model.name = "changed"
completion()
}
}
尝试这样做会导致错误:"Escaping closures can only capture inout parameters explicitly by value"。
您可以只向变量添加中间赋值。对于 class/reference 类型,这与在原始引用上设置 属性 具有相同的效果。对于结构类型,它会制作一个副本,这是行不通的,但应该通过扩展的约束来避免。
func changeModel(_ model: Model, completion: @escaping () -> Void) {
var modelRef = model
Api.shared.doRandomAsyncStuff() { (_) in
modelRef.name = "changed"
completion()
}
}
我试过这样的事情:
protocol MyModelProtocol {
var name: String { get set }
}
protocol MyProtocol {
associatedtype Model: MyModelProtocol
func changeModel(_ model: Model)
}
extension MyProtocol where Model: AnyObject {
}
编译器很高兴。但是,在这个扩展中,编译器仍然不确定 Model 是 class 还是 struct。示例:
extension MyProtocol where Model: AnyObject {
func changeModel(_ model: Model) {
model.name = "changed"
}
}
因此,我得到错误:"Cannot assign to property: 'model' is a 'let' constant"
我如何告诉编译器在该协议扩展中关联的类型将始终是 class?
顺便说一句,这只是一个简短的例子。我知道我可以在这种情况下使用 inout 参数,但它对我不起作用,因为我想像这样更改异步回调内部的对象:
func changeModel(_ model: inout Model, completion: @escaping () -> Void) {
Api.shared.doRandomAsyncStuff() { (_) in
model.name = "changed"
completion()
}
}
尝试这样做会导致错误:"Escaping closures can only capture inout parameters explicitly by value"。
您可以只向变量添加中间赋值。对于 class/reference 类型,这与在原始引用上设置 属性 具有相同的效果。对于结构类型,它会制作一个副本,这是行不通的,但应该通过扩展的约束来避免。
func changeModel(_ model: Model, completion: @escaping () -> Void) {
var modelRef = model
Api.shared.doRandomAsyncStuff() { (_) in
modelRef.name = "changed"
completion()
}
}