Battle of the iOS Architecture Patterns: Model View Presenter (MVP)

Radu Dan
Radu Dan
May 17 · 8 min read
Architecture Series — Model View Presenter (MVP)

Motivation

Before starting to develop an iOS app, we have to think of the structure of the project. We need to consider how we add those pieces of code together so they make sense later on — when we come back and revisit a part of the app — and how to form a known “language” with the other developers.

In this third article of the series, we will transform the MVVM app in MVP.
As usual, we will see how we apply the pattern to each screen, seeing the actual implementation and the source code. At the end, we will show the build times and detail some key observations about MVP, compared to the other architecture patterns.

If you just want to see the code, feel free to skip this post. The code is available open source on GitHub.

Why an Architecture Pattern for Your iOS App?

The most important thing to consider is to have an app that can be maintainable. You know the view goes there, that this view controller should do X and not Y. And more important, others know that too.

Here are some advantages of choosing a good architecture pattern:

  • Easier to maintain

Defining the Requirements

Given an iOS application with six or seven screens, we are going to develop it using the most popular architecture patterns from the iOS world: MVC, MVVM, MVP, VIPER, VIP, and Coordinators.

The demo app is called Football Gather and is a simple way for friends to track the scores of their amateur football matches.

Main features

Ability to:

  • Add players in the app

Screen mockups

Screen mockups of “Football Gather”, the iOS app

Backend

The app is powered by a web app developed in the Vapor web framework. You can check out the app in my Vapor 3 initial article and the article about Migrating to Vapor 4.

What is MVP

MVP is slightly the same as MVVM, but with some key notes:

  • You now have a presenter layer.

Model

  • The Model layer is exactly as in the others, it is used to encapsulate business data.

Communication

  • When something happens in the view layer, for example when the user initiates an action, it is communicated to the model through the Presenter.

View

  • View layer is the same as in MVVM, but the View now lacks responsibility for updating its state. The presenter owns the View..

Communication

  • Views can’t communicate directly with the Model, everything is done through the Presenter.

Presenter

  • Responsible for handling the events coming from the view and triggering the appropriate events with the Model.

Communication

  • Can communicate with both layers, Model and View/View Controller.

When to use MVP

Use it when you feel MVC and MVVM doesn’t work quite well for your use cases. You want to make your app more modularised and increase your code coverage.
Don’t use it when you are a beginner or you don’t have that much experience into iOS development.
Be prepared to write more code.

For our app, we separated the View layer into two components: ViewController and the actual View.
The ViewController acts as a Coordinator / Router and holds a reference to the view, usually set as an IBOutlet

Advantages

  • The separation of layers is better than in the other patterns.

Disadvantages

  • The assembly problem is revealed more prominently in MVP. Most likely you will have to introduce a Router or a Coordinator to take care of navigation and module assembly.

Applying to our code

There are two big steps we need to do:

  1. Go one by one through the ViewModels and turn them into Presenters

The applied MVP pattern is detailed below:

LoginPresenter

Let’s see how the LoginPresenter looks like:

All parameters will be injected through the initialiser.

The Keychain interactions are defined below:

And we have the two services:

The register function is basically the same as the login one:

The LoginView has the following protocols:

Most of the ViewController logic is now inside the View.

Finally, the ViewController:

We take screen by screen, and turn the existing MVVM architecture into an MVP.

PlayerListPresenter

Next screen is PlayerList, and we start with the web API calls:

Now, the check for playe deletion is made inside the Presenter and not in the View/ViewController.

If we look in the PlayerListView, at table view's data source methods, we observe that the Presenter is behaving exactly as a ViewModel:

The PlayerListViewController acts now more as a router between Edit, Confirm and Add screens.

Breaking into responsibilities, PlayerList module has the following components.

PlayerListViewController responsibilities:

  • Is implementing the PlayerListTogglable protocol to go back to the listView mode state, whenever a gather is completed (called from GatherViewController).

PlayerListView responsibilities:

  • Exposes the public API, PlayerListViewProtocol. This layer should be as dumb as possible and not do complex things.

PlayerListPresenter responsibilities:

  • At a first glimpse at PlayerListPresenterProtocol, we notice it does a lot of things.

PlayerListViewState responsibilities:

  • We decided to extract the ViewState into a new file, keeping the same functionality that we had in MVVM, using the Factory Method pattern to allocate the different states of PlayerListView.

PlayerDetail screen

Continuing with PlayerDetail screen, we separate the View from the ViewController.

Following the same pattern, the navigation to edit screen is done through delegation:

  • user taps one of the row that corresponds with a player property. The View tells the ViewController that we want to edit that field, the ViewController performs the correct segue. In prepare:for:segue method, we allocate the properties required to edit the player.

Inside PlayerDetailViewController:

PlayerDetailView is presented below:

And the table view delegate and data source implementation:

The PlayerDetailPresenter:

Edit Screen

We follow the same approach for the remaining screens of the app.
Exemplifying below the PlayerEdit functionality. The PlayerEditView class is basically the new ViewController.

The selectors are pretty straightforward:

And the Public API:

Finally, the UITableViewDataSource and UITableViewDelegate methods:

PlayerEditPresenter handles the business logic and exposes the properties for updating the UI elements.

An API call is detailed below:

PlayerAdd, Confirm and Gather screens follow the same approach.

Testing our business logic

The testing approach is 90% the same as we did for MVVM.

In addition, we need to mock the view and check if the appropriate methods were called. For example, when a service API call is made, check if the view reloaded its state or handled the error in case of failures.

Unit Testing below GatherPresenter:

Testing the countdownTimerLabelText:

Toggle timer becomes more interesting:

And below is the mock view:

I’d say that testing the presenter is very cool. You don’t need to do magic stuff, and the methods are very small in size which is helping.
The complex thing comes with the fact that you will need to mock the View layer and check if some parameters are changing accordingly.

Key Metrics

Lines of code — View Controllers

Lines of code — Views

Lines of code — Presenters

Lines of code — Local Models

Unit Tests

Build Times

Tests were run in iPhone 8 Simulator, with iOS 14.3, using Xcode 12.4 and on an i9 MacBook Pro 2019.

Conclusion

The application has now been rewritten from MVVM to MVP. The approach was straightforward, we took ViewModel by ViewModel and replaced it with a Presenter layer.

Additionally, we created a new layer — View — out of the ViewController to better separate the concerns. The code looks cleaner, view controllers are thinner, the classes and functions are small and concentrate doing one thing, embracing the Single Responsibility Principle.

I personally prefer this pattern rather than MVVM when it comes to apps developed with UIKit in mind. It feels more natural than MVVM.

Taking a look at the key metrics we can make the following notes:

  • the View Controllers are much thinner, overall we reduced their size with more than 1,000 lines of code

Really cool we saw together how to transform an app written in MVVM into a different pattern, such as MVP. From my point of view, MVP with the separation of View from the ViewController, is much nicer than MVVM. It brings more power to your layers, making them decoupled from each other and is much easier to use dependency injection.

Thanks for staying until the end! As usual, here are some useful links below.

Useful Links

Geek Culture

Proud to geek out. Follow to join our +500K monthly readers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store