VIPER Design Pattern in Swift for iOS Application Development.

Sayed Mahmudul Alam
6 min readMar 19, 2017

--

Everything that has a beginning, has an end -Gautama Buddha. Image Source: Screenshot taken from the movie “The Matrix Revolutions”

Design patterns are God’s gift to software developers. These are techniques that minimize code duplication, prevent high coupling, and standardize a common way of writing code that provides a general solution for recurring situations while developing software. In this story, we will get familiar with a design pattern called VIPER (View, Interactor, Presenter, Entity, and Router.) for iOS development.

Prerequisites: Before starting about VIPER, please make sure you know about architectural design patterns and delegation patterns.

What is Viper?

Viper is a design pattern that implements the ‘separation of concern’ paradigm. Mostly like MVP or MVC, it follows a modular approach. One feature, one module. For each module, VIPER has five different classes with distinct roles. No class goes beyond its sole purpose. These classes are following.

View: Class that has all the code to show the app interface to the user and get their responses. Upon receiving a response View alerts the Presenter.

Presenter: Nucleus of a module. It gets user response from the View and works accordingly. The only class to communicate with all the other components. Calls the router for wire-framing, Interactor to fetch data (network calls or local data calls), view to update the UI.

Interactor: Has the business logic of an app. e.g if business logic depends on making network calls then it is Interactor’s responsibility to do so.

Router: Does the wire-framing. Listens from the presenter about which screen to present and executes that.

Entity: Contains plain model classes used by the Interactor.

Below shows a simple diagram of VIPER

Viper Architecture

Viper with Example

I have created a simple project to explain viper. It can be found on GitHub. It is a very basic application that shows a list of news fetched from an external API.

Viper is a delegation-driven architecture. So, most of the communication between different layers executes through delegation. One layer calls another through a protocol. The calling layer calls a function from a protocol. The listening layer conforms to that protocol and implements the function.

Below I will explain how I have implemented VIPER in one of my sample projects. I suggest you open the project in GitHub and go through it while reading the explanation.

Protocols

I have created a separate file for all the protocols.

A naming convention is followed to name a protocol. e.g, ‘viewToPresenterProtocol’. So, it is a ‘protocol’ that will be implemented by ‘the presenter’ to listen to what the ‘view’ has to say.

  • PresenterToViewProtocol : Presenter calls, View listens. The presenter receives a reference from this protocol to access View. View conforms to the protocol.
  • ViewToPresenterProtocol: View calls, Presenter listens.
  • InteractorToPresenterProtocol: Interactor calls, Presenter listens.
  • PresentorToInteractorProtocol: Presenter calls, Interactor listens.
  • PresenterToRouterProtocol: Presenter calls, Router listens.

Also, our protocol names must be different for different modules. One way to achieve this is to add the module name as a prefix. So the format could be <Module-Name><Protocol-Name> e.g if the module name is Login then view to presenter protocol name will be LoginViewToPresenterProtocol. Our example project follows this convention which we will see further in the story.

App Flow

View has a reference of LiveNewsListViewToPresenterProtocol to access the Presenter and conforms to LiveNewsListPresenterToViewProtocol. In it’s viewDidLoad() it calls the function updateView() of the protocol.

// Viewvar presenter: LiveNewsListViewToPresenterProtocol?override func viewDidLoad() {        
super.viewDidLoad()
presenter?.updateView()
}

Presenter on the other hand conforms to LiveNewsListViewToPresenterProtocol. So, it implements the function updateView().

// Presentervar interactor: LiveNewsListPresentorToInteractorProtocol?func updateView() {
interactor?.fetchLiveNews()
}

Inside updateView() presenter tells the interactor to fetch some live news data.

Interactor conforms to LiveNewsListPresentorToInteractorProtocol . So it implements fetchLiveNews() function. This function makes a network call and fetch data. It has a reference from LiveNewsListInteractorToPresenterProtocol to access the Presenter.

// Interactorweak var presenter: LiveNewsListInteractorToPresenterProtocol?

If the network call successfully has fetched the data it calls the following function.

// Interactorguard let articles = newsResponse.articles else { return }                    self.news = articles
self.presenter?.liveNewsFetched()

if not

// Interactorself.presenter?.liveNewsFetchedFailed()

Now presenter also conforms to LiveNewsListInteractorToPresenterProtocol. So it implements these functions.

// Presenterfunc liveNewsFetched(news: [LiveNewsModel]) {
view?.showNews()
}
func liveNewsFetchedFailed(){
view?.showError()
}

So it tells the view whether to show news or to show an error.

Now, View conforms to LiveNewsListPresenterToViewProtocol. Thus it implements showNews() and showError(). In these two functions view populates the view with the fetched data or the error.

// Viewfunc showNews() {
tableView.reloadData()
}
func showError() {
//write error showing code here
}

The Entity Layer

In the app flow section, the entity layer is not discussed. It is not directly connected with the app flow, but an integral part of the Interactor. The entity layer provides a model which the Interactor uses to create objects from the fetched data. One thing to remember about the Entity is out of all the layers only the Interactor should own an entity. The diagram above also shows that Entity only communicates to the Interactor. But the question here is then how the View will know about the entity? It has to show the data, right? The short answer is View will call the Presenter to get it and the Presenter will get it from the Interactor. E.g we have cellForRowAt where we populate a table view cell.

// Viewfunc tableView(_ tableView: UITableView, cellForRowAt indexPath:   IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "LiveNewsTableViewCell", for: indexPath) as? LiveNewsListTableViewCell
let row = indexPath.row
let news = presenter?.getNews(index: row)
guard let title = news?.title, let author = news?.author, let description = news?.description else {
return cell ?? UITableViewCell()
}
cell?.setCell(title: title, author: author, description: description) return cell ?? UITableViewCell()
}

Here at this below line, the data is requested from the presenter.

// Viewlet news = presenter?.getNews(index: row)

Then Presenter gets it from the Interactor.

// Presentervar news: [LiveNewsModel]?func getNews(index: Int) -> LiveNewsModel? {
return interactor?.news?[index]
}

So the main point here is that only the Interactor will have an instance of the Entity.

Router

The router takes care of the wireframing of an application. Changing the screen in an application is a very basic thing. In VIPER, the Router layer is responsible for executing that.

We have discussed earlier that in VIPER architecture every single feature has a single module and a module contains those five layers. A presenter calls the router to create a new module. Then router first initiate all the layer class and returns the module.

In my sample project, there is no module change happening. But routing does happen when the app first time launches. So inside AppDelegate’s didFinishLaunchingWithOptions(), router’s createModule() function is called. It returns a module. UIWindow class then shows the View of that module.

Why and When to use VIPER

VIPER follows a very clean architecture. It isolates each module from others. So changing or fixing bugs is very easy as you only have to update a specific module. Also for having a modular approach VIPER creates a very good environment for unit testing. As each module is independent of others, it maintains low coupling very well. So, dividing work among co-developers is also pretty simple.

VIPER should be used when an application’s requirements are very well-formed. Working with constantly changing requirements may create confusion and messed-up codes. So, it should not be used in small projects as MVP or MVC will suffice. Also, VIPER should be used if all the developer of the project fully understands the pattern.

VIPER Tools

If one wants to use VIPER in a project, the smartest thing would be to use an automatic module structure generator. Otherwise creating files for modules will be monotonous. There are few generators available online.

Conclusion

Just like any other design pattern VIPER is self-explanatory. One needs to get one’s hands dirty to understand the whole picture. My advice will be to first start creating a very basic app with VIPER and simultaneously read online resources. My GitHub repo could also be a good starting point.

Happy coding :)

Long live sacred Bangladesh.

Bangladesh is a world of metaphor, of high and low theater, of great poetry and music. You talk to a rice farmer and you find a poet. You get to know a sweeper of the streets and you find a remarkable singer.

Jean Houston

Reference :

  1. https://medium.com/ios-os-x-development/ios-architecture-patterns-ecba4c38de52
  2. https://medium.com/@ankoma22/the-good-the-bad-and-the-ugly-of-viper-architecture-for-ios-apps-7272001b5347
  3. https://github.com/MindorksOpenSource/iOS-Viper-Architecture/tree/master/iOS-Viper-Architecture
  4. https://sourcemaking.com/design_patterns

--

--