MVC was adopted by Apple as an official architectural pattern for iOS. Where :
- The view : is a xib file (or a UIView subclass).
- The Controller : A UIViewController subclass, which receives actions and events from the view and updates it.
- And Models : that are a representation of your data.
The problematic :
MVC intended initially to distribute the applications components among separate pieces. But generally the result was :
Lack of Distribution : The controller ends up doing all the job. from handling user interactions, to setting up views. doing network calls, data parsing and so and so on…
This is also known as Massive view controller.
Low test coverage : Apart from breaking the single responsibility principle. the controller is tightly linked to the view lifecycle. testing view controllers becomes a tough task.
MVP As an alternative :
Then MVP architecture comes to improve this situation. by adding the main component which is Presenter.
Hold on a second ! i know this looks like MVC, but with a key difference :
Now the viewController is considered as a view. which means it will include only the view related code, nothing more. and all logic will be implemented in the presenter.
Then components description becomes as the following :
- View : The view now consists of both views and view controllers, with all UI setup and events.
- Presenter : The presenter will be in charge of all the logic , including responding to user actions and updating the UI (via delegate). and the most important is that our presenter will not be UIKit dependent. which means well isolated, hence easily testable ;)
- Model : the model role will be exactly the same
It’s important to note that MVP uses passive View pattern. it means all the actions will be forwarded to the presenter. Which will trigger the ui updates using delegates. so the view will only passe actions and listen to the presenter updates.
No more talking. let’s get hands dirty !!
Let’s create a single page project in swift , i guess you know how to do it ;)
Then we will create the model. a simple struct called Traffic Light, which has two properties. one for color name and the other for the description of its traffic status.
A service class which will play the role of data provider. As we mainly use web services in real applications. It simply returns a model by its name.
TrafficLightViewDelegate protocol which contains all the methods that will be implemented in our view or (ViewContoller).
We will use it when ever we want to pass an information from the presenter to the view. Here it will allow to send the information back to the view controller.
Then, we have the Presenter, the main component :
Then presenter has two properties :
- The first one is the TrafficLightService. which is owned by the presenter.
- And the second is a weak Refenrece of the view delegate. since the presenter itself will be owned by the view (or the view controller)
Then trafficLightColorSelected will be used to forward the event of selecting a trafic Color from the view to the presenter.
Then in the main storyboard. Add a viewController screen with three buttons and one label.
And finally here is our traficViewController. which is now nothing more than a view.
The view owns a presenter. initialized with service class.
Whenever we have an action. we call the presenter. the red light action calls trafficLightColorSelected method. with the related color name. and so and so on.
And displayTrafficLight will be called from the presenter providing the right description.
And here is the final project structure :
Here is the full example source code .
This is how the presenter will be the main actor in our application without using the UIKit framework. and without creating a massive viewcontroller.
In the same time we isolated the logic from the views lifecycle in a way it will be easy to do unit tests.
However, this is not a perfect solution knowing that the presenter will have too much work to do. then we will not be respecting the single responsibility principle.
More evolved architectures were invented to resolve those issues such as VIPER, CLEAN, MVVM… That i will try to cover in future posts. Thank you !!!