Sitemap
Better Programming

Advice for programmers.

Implement a VIPER Architecture in Swift 5

Leverage the Single Responsibility Principle

4 min readJan 3, 2020

--

Press enter or click to view image in full size
Photo by Alex wong on Unsplash

In this tutorial we will learn how to implement a VIPER architectural pattern in Swift 5.

I have created a demo app that uses The Simpsons Quote API to fetch quotes, characters, and image URLs from “The Simpsons.”

The actual images are obtained using Kingfisher.

For code generation, I’ve created my own VIPER Xcode template.

The source code of the project is available here.

NOTE: The Simpsons Quote API is published on a free platform, so it’s possible that you may get a 400 error when using network requests too often. Try not to spam the requests, otherwise you will have to wait for some time until the API becomes available again:

Press enter or click to view image in full size

Simpsons Quotes

Press enter or click to view image in full size
Press enter or click to view image in full size

Project Structure

The root of the project is divided into three folders: Classes, Resources, and Supporting Files. The Resources folder contains Assets.xcassets, and the Supporting Files folder contains LaunchScreen.storyboard and Info.plist.

As you can see, in Classes, we have the following folders:

  • App contains AppDelegate.swift
  • Modules has two defined modules: Quotes and QuoteDetail
  • Common contains the REST API endpoint and Entities [aka models in MV(X)]
  • Managers includes classes that facilitate our work with the REST API
  • Services contains QuoteService (retrieves quote entities from the REST API), ImageDataService (converts data into UIImages), and KingfisherService (obtains image data using the image URL from the quote entity)

Let’s Define a VIPER Module

A typical VIPER Module consists of five components: View, Interactor, Presenter, Entity, and Router. Here is a short description of what each component does:

  • View is passive and doesn't do much on its own. Its sole responsibility is to message events to the presenter and display UI elements.
  • Interactor is a UIKit-independent component that performs all business logic. For example, in our app, it uses Services to communicate with the REST API in order to obtain image data from an URL.
  • Presenter is also UIKit-independent. It receives messages from the view and decides whether to send messages to the interactor or the router. It also receives the data from the interactor and prepares it for the view to display in the suitable format.
  • Entity is a plain model that’s used by the interactor
  • Router, in our app, is responsible for creating a particular module and navigating from one module to another

To Our App: Quote Module

First, we should define the contract (five protocols in our case) according to which VIPER components will interact with each other.

QuoteContract.swift

  • View input (ViewToPresenterQuotesProtocol): Presenter should conform to that protocol. Presenter receives messages from the view and tells the interactor what it should do.
  • View output (PresenterToViewQuotesProtocol): The ViewController should conform to that protocol. The view receives the operation result from the presenter and acts accordingly to its logic:
  • Interactor input (PresenterToInteractorQuotesProtocol): The interactor should conform to that protocol. Here’s the workflow: In the view, we notify the presenter some event happened (e.g., viewDidLoad). The presenter, in its order, tells the interactor it should perform a certain task (e.g., loadQuotes). After the task’s completed, the interactor forwards the result back to presenter.
  • Interactor output (InteractorToPresenterQuotesProtocol): The presenter should conform to that protocol. These methods are called in the interactor input after the interactor completes its task (as seen above). After receiving of a task from the interactor, the presenter prepares the received data in the displayable format for the view and sends messages to it. What the view does in these result methods (onFetchQuotesSuccess, onFetchQuotesFailure) is shown in view output above.
  • Router input (PresenterToRouterQuotesProtocol): The router conforms to that protocol. The router creates the quote module and configures the dependencies. It waits for the command from the presenter to navigate to another screen, passing the selected quote as a parameter:

QuoteDetail Module

In QuoteDetail, the workflow is the same.

Workflow

  1. The view tells the presenter that it’s been loaded:

2. The presenter tells the interactor to get the image data:

3. The interactor uses KingfisherService to load the image from a quote’s URL and sends the result back to the presenter:

4. The presenter receives the result from the interactor, prepares the data to be in the correct displayable format, and sends the result to the view:

5. Finally, the view gets the result from presenter and displays/updates its UI elements:

Wrapping Up

You may have noticed how VIPER clearly separates the responsibilities between its five core components: View, Interactor, Presenter, Entity, and Router. In fact, VIPER is based on the Single Responsibility principle (S from SOLID).

If you are curious about other architectural patterns, feel free to check out some of my relevant pieces:

Thank you very much for reading!

--

--

Responses (2)