VIPER Design Pattern in Swift for iOS Application Development.

Everything that has a beginning, has an end

Design patterns are God’s gift to software developers. These are techniques that minimize code duplication, prevents high coupling and standardize a common way of writing code that provides a general solution for reoccurring situation while developing a 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 learning about VIPER, please make sure you know about architectural design pattern and delegation pattern.

What is Viper ?

Viper is a design pattern that implements ‘separation of concern’ paradigm. Mostly like MVP or MVC it follows a modular approach. One feature, one module. For each module VIPER has five (sometimes four) different classes with distinct roles. No class go 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 response. Upon receiving the response View alerts the Presenter.

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

Interactor: Have business logics of an app. Primarily make API calls to fetch data from a source. Responsible for making data calls but not necessarily from itself.

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

Entity: Contains plain model classes used by interactor.

Below shows a simple diagram of VIPER

Viper Architecture

Viper with Example

I have created a simple project to explain viper. It is a very basic application. It just shows a news headline fetched from an external API. (how useless :p) It is uploaded on github.

Viper is a delegate driven architecture. So, most of the communication between different layers executes through delegation. One layer calls another through a protocol. Calling layer just calls a function from a protocol. Listening layer conforms to that protocol and implements the function.

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

Protocols

I have created a separate file for all the protocols.

I have followed a naming convention to name protocols. Like ‘viewToPresenterProtocol’ . So, it is a ‘protocol’ which will be implemented by ‘the presenter’ to listen what the ‘view’ has to say.

  • PresenterToViewProtocol : Presenter calls, View listens. 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.
  • PresentorToInterectorProtocol : Presenter calls, Interactor listens.
  • PresenterToRouterProtocol : Presenter calls, Router listens.

App Flow

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

//View
var presenter: ViewToPresenterProtocol?
override func viewDidLoad() {        
super.viewDidLoad();
presenter?.updateView();
}

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

//Presenter
var interector: PresentorToInterectorProtocol?;
func updateView() {
interector?.fetchLiveNews();
}

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

interactor conforms to ‘PresentorToInterectorProtocol’ . So it implements fetchLiveNews(). This function tries to make a network call and fetch live news data. It has a reference from ‘InterectorToPresenterProtocol’ to access the ‘Presenter’.

//Interactor
var presenter: InterectorToPresenterProtocol?;

if the network call successfully have fetched the data it calls the following functions.

//Interactor
self.presenter?.liveNewsFetched(news: (arrayObject?[0])!);

if not

//Interactor
self.presenter?.liveNewsFetchedFailed();

Now presenter also conforms to ‘ InterectorToPresenterProtocol’. So it implements these functions.

//presenter
func liveNewsFetched(news: LiveNewsModel) {
view?.showNews(news: news);
}
func liveNewsFetchedFailed(){
view?.showError()
}

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

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

The Entity Layer

Above in the app flow section entity layer is not discussed. It does not directly connected with the app flow. But it is a integral part for the interactor. Entity layer provides a model which interactor use to create objects from the fetched data.

Router

Router takes care the wire framing of a application. Changing window in a application is very basic thing. It has to happened a lot of times. In VIPER, Router layer is responsible for executing that.

We have discussed earlier that in VIPER architecture every single functionality 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 in-app module changing. 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 show 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 are very easy as you only have to update a specific module. Also for having moduler approach VIPER creates a very good environment for unit testing. As each module is independent from others, it maintains low coupling very well. So, dividing work among co-developers are pretty simple.

VIPER should be used when a application’s requirements are very well formed and mostly fixed. Working with constantly changing requirements may create confusion and messed up codes. So, it should not be used in small project 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 the project the smart thing would be to use a automatic module structure generator. Otherwise creating files for modules will be monotonous. There are few generators available on-line.

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 with creating a very basic app with VIPER and in the process read online resource. My github repo could also be a good reference.

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