Reputation: 32809
Let's say I have the following infrastructure:
protocol Naming {
var printer: Printer { get }
var name: String { get }
}
extension Naming {
var name: String { return "\(type(of: self))" }
func printName() {
printer.print(name)
}
}
protocol Printer {
func print(_: String)
}
I have a protocol that exposes a name and a printer, that is used to print the name.
Now, trying to follow MVC, I add these:
protocol ModelInjectable {
associatedtype Model
var model: Model { get }
}
extension Naming where Self: ModelInjectable, Self.Model: Naming {
var printer: Printer { return model.printer }
var name: String { return model.name }
}
which allows view controllers to specify they allow a model, and in such cases allow them to conform to Naming
by simply forwarding the protocol conformance to the model.
This is a simple VC:
class MyViewController: UIViewController, ModelInjectable, Naming {
let model: MyModel
required init(model: MyModel) {
self.model = model
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError()
}
}
The problem arise when I try to use a protocol for the model:
struct MyModel: Naming {
let printer: Printer
}
works as expected, however
protocol MyModel: Naming {
}
gives compile errors:
error: type 'MyViewController' does not conform to protocol 'Naming' class MyViewController: NSViewController, ModelInjectable, Naming {
note: candidate has non-matching type 'Printer' var printer: Printer { return model.printer }
note: protocol requires property 'printer' with type 'Printer'; do you want to add a stub? var printer: Printer { get }
From what I can tell, the extension Naming where Self: ModelInjectable, Self.Model: Naming
extension is used by the compiler only when using a concrete type. Using a protocol reference doesn't do the trick. Is this a limitation of the compiler, or am I wrongly using the feature?
Upvotes: 1
Views: 368
Reputation: 135548
Unlike e.g. Objective-C protocols, a Swift protocol doesn't conform to itself. As a result, protocol MyModel: Naming
doesn’t satisfy the Self.Model: Naming
constraint of your protocol extension.
Upvotes: 1