VIP Architecture in iOS

An overview of getting started with Clean Architecture

Ayush Singhi
5 min readMar 27, 2021
Source — Self-created😎

Hello 😎!

In this article, we are going to discuss how to get started with VIP Architecture in iOS. We shall begin by looking at certain theoretical backgrounds to understand the basic working and data-flow in VIP. Following which we will dive into some real code.

Topics that shall be covered are —

  1. Why VIP?
  2. VIP: View Controller, Interactor, Presenter
  3. VIP Cycle and Data flow
  4. Implementing VIP in iOS

Why VIP?

To begin with, you may have worked with various system architectures such as MVC, MVVM, ReactiveCocoa, or VIPER which have been “good” and did a great job until recently. These architectures have been helpful in building and publishing various apps. However, they have not been “good” in efficiently managing the problems of scalability and maintenance.

This is due to the underlying issues in the design and data flow patterns of these architectures that make them challenging and nonreliable often leading to Massive View Controller. Further, there may be bugs and difficulties in adding new features which makes the use of these architectures more cumbersome.

Clean VIP Architecture is what offers a solution to the above-mentioned problems.

VIP: View Controller, Interactor, Presenter

VIP is Uncle Bob’s Clean Architecture. It is one of those system architectures that follow clean architecture guidelines about system design, component design, data flow between different system layers, and others. It consists of three core components:

  1. ViewController: It is a UIViewController that we encounter frequently with the mere difference that in VIP it has only two responsibilities, namely, getting user inputs and rendering UI. In addition, it also holds a strong reference to Interactor.
  2. Interactor: In VIP, Interactor is a concrete class with the functions of making various API calls and maintaining data and business logic. It holds a strong reference to the Presenter.
  3. Presenter: The presenter is also a concrete class that holds a weak reference to Controller. It performs the functions of creating and passing data to ViewController via ViewModels and validating data and actions for ViewController.

Hence, the responsibilities in VIP are nicely divided into various classes leading to a clear separation of UI and business logic, unlike other architectures.

Note that a few other entities like — Models and Routers that facilitate navigations and data maintenance have not been broadly discussed here.

VIP Cycle and Data flow

The VIP cycle and data flow is as follows—

ViewController → Interactor → Presenter → ViewController

A basic representation of VIP Cycle and data flow
  1. ViewController takes user inputs and passes them to Interactor in form of requests.
  2. Interactor processes these requests (validates and executes them) and passes the response to the Presenter
  3. Presenter processes these responses (validates and creates ViewModels) and passes them to ViewController to update/render UI.

From above, it is clear that the data flow in VIP is uni-directional, from View -> Interactor -> Presenter -> View. This way VIP tackles certain problems that arise in bi-directional data flow architectures like MVC, MVVM, and others.

VIP in iOS: Implementation

Now comes the final step of implementing VIP in an iOS Project.

For simplicity, the example is restricted to only one view, which displays a list of Movies that have an imdbRating > 8.0 . This is achieved via a UITableView and a set of prefetched movie data stored in a JSON file in the App bundle.

A view of the final app which displays a list of movies

Models — Movie.swift

In order to display the above data, we will create Movie , a model that will map data for each movie.

Worker — FileReader.swift

This is a Worker class that reads data from the static JSON file saved in the App bundle.

FileReader is a Worker that has a static method getMovies(:)to read data from JSON files and send Result in a callback .

ViewController — MoviesListController.swift

This is a UIViewController class that controls the UI of the App.

Notice that the controller in the above code holds an optional reference of the interactor , which is used to pass user and data requests from the controller to interactor as is evident from the usage of the method viewWillAppear(:) .

Besides, MoviesListController also has a render(props:) which is the only method responsible for updating the view as is suggested by the theory. This helps in debugging and maintaining update logics for the view.

Interactor —MoviesListInteractor.swift

The following snippet shows the interactor performing its core responsibilities — getMovies(:) to get data and processMovies(:) to implement business logic.

Here, interactor fetches data for movies , processes it and then triggers an update in the presenter . Hence, passing response from interactor -> presenter

Presenter — MoviesListPresenter.swift

This section shows the presenter , performing its core responsibility— updating controller with the new data passed to it.

It is worth noting how in the method updateView(:) , presenter reads the current state of controllers viewProps and updates only the required data and then triggers the render(:) method that would start the view update. So, passing data from presenter -> view . With this, the VIP cycle which is a uni-directional data flow is completed.

Router — Router.swift

In VIP, Router is a class facilitating navigation from one view to another. Generally, each view has its own Router but, it is not always necessary as there can be a global Router class that may be divided into various sub-routers whilst maintaining the navigation stack. In the example below, a global Router is created that has its own navigationController .

Observe how the method showMoviesListView() is used to show the Movies list view. This method instantiates the controller, presenter, interactor and passes the reference of one entity to another. This is a very apt representation of the VIP cycle.

Once all the relations are established, the view is pushed onto the navigation stack which brings us to the end of VIP implementation.

The only thing left now is to call the startNavigation() to start navigating and presenting views. This can be done either in AppDelegate or SceneDelegate classes. Based on my deploymentTarget i.e. iOS 14.2, I have done that in SceneDelegate .

This brings us to the end of the article. All that is left now is to run the App.

Hope that now you can try and create your own iOS Apps that follow the Clean VIP Architecture and play around with your code in this amazing way whilst noticing the immense scope of VIP.

If you want the complete source code of the above example, visit the Github repository given below—

See you soon! Until then,
Happy Coding!💻📱

--

--