I have a base protocol that describes the router behavior:
protocol BaseRouterProtocol: AnyObject {
associatedtype View: MainView
func dismiss(viewController: ViewController<View>?)
}
extension BaseRouterProtocol {
func dismiss(viewController: ViewController<View>?) {
viewController?.navigationController?.popViewController(animated: true)
}
}
I want to adopt this protocol to another like this:
protocol StartRouterProtocol: BaseRouterProtocol where View == StartView {
func showTermsVC()
func showSignInVC()
}
But when I create a variable of this type:
let router: StartRouterProtocol
Compiler throws me an error:
Protocol 'StartRouterProtocol' can only be used as a generic constraint because it has Self or associated type requirements
Why does this happening if I have described the type that I expect?
Once a protocol has an associated type, that protocol can't be used as a type by itself for instance declarations-- only for generic constraints and declaring conformance.
So in this case, Swift is saying "yeah, but what is the concrete type for StartRouterProtocol
's associated type?"
In this case, it's asking you to either:
let router: MyStartViewClass
with this conformance declaration, elsewhere: class MyStartViewClass: StartRouterProtocol { ... }
)class MyRouterController<T: StartRouterProtocol> {
let router: T
}
This is probably not what you were hoping for, but unfortunately associated types add complexity to how you use protocols, especially if you're familiar with generics & interfaces from other languages. (i.e. Java/C# interfaces)
You can work around some aspects of associated types by using a concept called "type erasure" -- but that can cause other problems and complexity.
Here's some further reading that may help: https://medium.com/monstar-lab-bangladesh-engineering/swift-from-protocol-to-associatedtype-then-type-erasure-a4093f6a2d08