3

I'm trying to write a simple MVP pattern to follow in my app, so I've written two porotocols to define View Controller and Presenters:

protocol PresenterType: class { associatedtype ViewController: ViewControllerType var viewController: ViewController? { get set } func bind(viewController: ViewController?) } protocol ViewControllerType: class { associatedtype Presenter: PresenterType var presenter: Presenter { get } init(presenter: Presenter) } 

After having those defined I started writing some RootViewController and RootViewPresenter. The latter looks like:

protocol RootViewControllerType: ViewControllerType { } final class RootPresenter<VC: RootViewControllerType>: PresenterType { weak var viewController: VC? func bind(viewController: VC?) { self.viewController = viewController } } 

Up to this point everything complies and is fine, but when I start implementing View Controller like this:

protocol RootPresenterType: PresenterType { } final class RootViewController<P: RootPresenterType>: UIViewController, ViewControllerType { let presenter: P init(presenter: Presenter) { self.presenter = presenter super.init(nibName: nil, bundle: nil) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() presenter.bind(viewController: self) } } 

Immediately I get the following error message:

Cannot convert value of type 'RootViewController

' to expected argument type '_?'

I know that protocols with associated types can introduce some limitations, but this example is pretty straightforward and I can't make it work. Is it possible to achieve something that I want, or do I have to look for some other, less Swifty pattern?

1
  • I am not sure if two protocols can use eachother if they both have associated types Commented Nov 27, 2018 at 21:31

1 Answer 1

2

I don't think what you're trying to achieve is possible due to the circular dependency between the respective associated types of the PresenterType and ViewControllerType protocols.

Consider for a moment if the suspect code above did compile ... how would you go about instantiating either the RootPresenter or RootViewController classes? Because both depend on one another, you'll end up with errors like the following:

Generic parameter error 1. Generic parameter error 2.

As you can see, the compiler can't fully resolve the generic parameters due to the associated types.

I think your best bet is to remove the associated type from one or both of the protocols. For example, removing the associated type from the PresenterType protocol and updating the RootPresenter class breaks the circular dependency and allows your code to compile normally.

protocol PresenterType: class { var viewController: UIViewController? { get set } func bind(viewController: UIViewController?) } final class RootPresenter: PresenterType { weak var viewController: UIViewController? func bind(viewController: UIViewController?) { self.viewController = viewController } } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.