protocol ValueProtocol {
init(_ string: String)
}
protocol Model: AnyObject {
associatedtype Value: ValueProtocol
var value: Value { get set }
}
The code below doesn't compile and it fails with Command SwiftEmitModule failed with a nonzero exit code.
let models = [any Model]()
for model in models {
model.value = .init("Lorem Ipsum") ❌
}
But this one does
func initialiseValue(of model: some Model, with string: String) {
model.value = .init(string)
}
let models = [any Model]()
for model in models {
initialiseValue(of: model, with: "Lorem Ipsum")
}
I undestand the initialiseValue function is implicitly opening any Model and that's why it works but shouldn't the the first code also compiles because the init is common to any type that implements ValueProtocol?
As an alternative to the standalone function that takes "some Model" you may put initialiser function onto the protocol itself:
protocol ValueProtocol {
init(_ string: String)
}
protocol Model: AnyObject {
associatedtype Value: ValueProtocol
var value: Value { get set }
func initialiseValue(with string: String)
}
let models = [any Model]()
for model in models {
model.initialiseValue(with: "Lorem Ipsum") // ✅
// model.value = .init("Lorem Ipsum") ❌
}
Also this
And if you can remove self / associated type requirement from the protocol you'd be able using Model in a pure existential manner (which might not be exactly what you are looking for, but just in case):
protocol ValueProtocol {}
protocol Model: AnyObject {
var value: ValueProtocol { get set }
func initialiseValue(with string: String)
}
let models = [Model]() // no "any" here
for model in models {
model.initialiseValue(with: "Lorem Ipsum")
}