P.S:
This is not a opinionated question. Its a legitimate doubt on wiring various modules in VIPER. Its a theoretical question so no code attached. I just need to know how do we wire up View-Presenter-Router in this specific case without breaking ground rules of VIPER
I am trying my hands-on with VIPER for the first time. Here is my fundamental understanding of VIPER.
View: Supposed to show UI Controls and capture IBActions and call its presenter's delegate method to process events
Presenter: Will process all the UI related data and prepares data for rendering and hands over the data back to View. Whenever a screen transition is required it calls its router and asks the router to perform transition
P.S: Presenter will not have any UIComponents in it. So no import UIKit statement in presenter.
Router: is responsible for performing screen transitions usually does it with the help of wireframes (optional but good to have such class in app)
Interactor: Contains all business logic.Presenter will call Interactor whenever processing based on business logic is required.
Entity: POJO classes (Simple Swift Objects or Core data entities).
Now comes the question:
If my assumptions are right, Presenter is supposed to be a plain Swift class with no UIKit access.
If true, assume I press a button on my ViewControllerA and I need to push another ViewControllerB on top of it, obviously ViewControllerA will talk to PresenterA and tells it that button is tapped, now PresenterA should talk to RouterA and tell it to push ViewControllerB.
Because Router can have access to UIKit I can easily create a new instance of ViewControllerB using storyboard instance or from xib, but in order to push that instance I need the ViewControllerA's instance.
But PresenterA can not hold a reference to ViewControllerA or can be passed as argument to PresenterA in function because UIViewController belongs to UIKit and Presenters are not supposed to have UI statements.
Probable Solutions I can think of:
Solution 1:
While creating Router instance, pass corresponding ViewController instance as a part of its init (Dependency injection phase) that way Router will always have reference to ViewController it belongs to
Solution 2:
Have a Router declare its protocol and implement it in ViewController and whenever reference to ViewController needed use delegate of Router. But this contradicts the rules of VIPER that routers are not supposed to talk to View.
Am I thinking straight? Am I right with my assumptions? If yes what is the correct way to deal with this problem, Please suggest