Mikhail Muzhev

VIPER Swift

What is
VIPER
VIPER model is separation of MVC to few parts. These parts are called View, Interactor, Presenter, Entity, Router.

View — is showing content on screen, i. e it contains some UIViews. View is passive and has no any business logic here.
Interactor — all business logic of application should be here.
Presenter — it provide data from Interactor to View and vice versa.
Entity — it's a class which contains only properties. For example Human class, it has properties like age, weight, height. Entity just like View has no any business logic.
Router — it's responsible for module routing, i. e navigation between application screens.

Interactor can't contact with View and vice versa. It has the same situation with Router. Presenter works as a connector between all of them.

The parts of module should be wrapped by protocols and connect with each other only by protocols, except Router. Also we can't pass Entities between parts, only Interactor can work with Entities.
What does it need for
1) It helps to add and change the code. Methods are more atomic because of using the principle of single responsibility. That’s why programmer doesn’t need to rewrite all code when he want to add some new feature, he should only work with few methods. It greatly accelerates the development.

2) It makes the code more testable, because of more atomic methods too — they are not black box for testing with a big variety of results.
Issues
Everything is clear and easy in theory, but there are some troubles in reality.
The first and the main problem — dependencies between parts of VIPER-module (Presenter, Interactor, etc.) There are 2 ways to solve this problem:
1) Inject all dependencies by own hands
2) Use some libraries for dependency injection (for example Typhoon).

The first variant is more complicated and waste more time than the second. Programmer have to inject dependencies in the right way and do it without memory leak. Why it's leaked? It happens because of double connections — Router has strong reference to Presenter, on the other hand, Presenter strong reference to Router. The same thing is between View and Presenter. To solve this problem we use 1 weak reference to object (from Presenter to View, from Presenter to Router) instead of 2 strong. So there are no cycles now and object will be destroyed when it become useless. Main advantage of this method — everything is clear and programmer controls live cycle of objects.

Using libraries can make programmer happier, because he doesn't have to think about dependency injection. But there is some new problem here — libraries could be changed or dissapeared. Taking into consideration the fact that the library is responsible for connectivity of application, missing of this library will be catastrophic. If it's happened, developer have to find new library or inject all dependencies by himself. Anyway, it wastes a lot of time.

Another trouble is that big part of libraries and some standard features of Swift and Objective C aren't compatible with VIPER (for example UITableVIew). It's often happened because principle of single responsibility is breaking by these things. Some of this errors we found in our project — before changing application structure to VIPER, we use some textField which has his own email validation. It's called from instance of this textField class. So there is logic inside View-layer. There are some ways to solve it:
 — forget about single responsibility principle and leave well enough alone;
 — send this textField to Interactor, but it's not simple object => breaking the VIPER principles;
 — remove library from project and write validation methods inside Interactor by our own hands;

There is not so big problem here, which is solved very fast (we choose last way and write everything without library), but sometimes it can be very difficult to find way to fix it and not break VIPER principles. Anyway it waste a lot of time and require clever developer.
Dependency injection
Mutual mobile recommend to merge all dependencies in one method and call it in appDelegate class when application is starting. This approach has two serious disadvantages:
1) If application has many strings of code, method with dependencies will be extremely huge and hard to understand.
2) When this method is calling all this heap of depending from each other objects is waisting a lot of memory.

First disadvantage fixes fast and easy. It can be solve by dividing this method into several parts. Every part responsible only for 1 VIPER-module. Situation with second disadvantage is much more interesting. The best solution is "lazy" initialization. I’ll show it in few steps:

Let’s create class Assembly for every VIPER-module, which has assembleModule method:
This method collect all dependencies of his module and return Router.

Example:
There are 2 modules: Start and Options. Start is first screen, then with tapping button we are going to Options.
Inject dependencies for Start-module with StartAssembly. assembleModule () method. After that we are making method injectOptionsDependencies inside StartRouter:
Next step is calling the injectOptionsDependencies () in presentOptions (), which navigate us to Options screen.
So, now memory isn't wasted for nothing.
Using UINavigationController to navigate between modules
As navigation system we use UINavigationController. Create method pushViewController in Router for it:
Dependency connections:
NavigationController has strong reference to View, View to Presenter, Presenter to Interactor and Router. So we have that NavigationController hold the all module. As a result, this solution allow us to destruct all module after ViewController will be removed from NavigationController.
TableViewDelegate and TableViewDataSource
The method, which we recommend to use, is not the only possible way. It was created for lack of anything better. Let’s show it with example.

There is array of Human objects, which is asynchronous received with the help of some API. Human has properties:
 — Name: String;
 — Age: Int;
 — Photo: UIImage;
For displaying information use UITableView is using. Name, age and photo of Human are loaded into cell.

One of VIPER principles says that View is passive, but Presenter must return nothing to View. View should has setters, which Presenter uses for displaying information. The problem is that it works only for objects which are already created, but not for dynamically created. It means, you can’t write setter for every cell, because. Why is that? First of all, when application is written, the quantity of cells is unknown. Secondly, writing setters for the same objects is foolishly.

Solution:
Let’s create variable for each property of Human inside View, then add setter for every new variable.
Next, create method in Presenter, which gets data from Interactor and set it to "currentHuman" variables from View:
In this way every cell is filled with right data. It corrupts principle, which said that View shouldn’t has anything except references to UIViews and to Presenter. But it observes an other rules and code is still testable.
Transfer objects between modules
For reasons unknown to us nobody describes this process, but it’s actual, and it will have to be faced with. Let’s add some features to the previous example with the list of Humans. Human has some new properties: biography and living address. After some cell is selected it’s navigate to screen with full info of Human. This full info screen is another module, so it means that you need to provide Human from table to the new screen.

VIPER principles said that modules can collaborate only by Router. But router has no access to Human entity, it’s located in Interactor. What have we done:
 — wrap Human to NSObject (Human is a derived class of NSObject) and get it from Interactor:
— then, create setter in FullInfo Interactor, which unwrap Human:
— also, implement setter in FullInfo Presenter:
— the same step for FullInfo Router:
— and again implementing, but now for Humans Router:
— and the last step, send Human from Humans Presenter:
Unfortunately, we corrupt one principle — Interactor shouldn’t pass Entities. But while object is "traveling", it is a simple object for all parts of modules except Interactors of sender and receiver. This way, we abstracted from details of Human entity realization. And now if we need to change Human class, we have to change only getter and setter of it in Interactors.
Thanks for reading!