Swiftorial Logo
Home
Swift Lessons
Matchups
CodeSnaps
Tutorials
Career
Resources

VIPER Pattern Tutorial

Introduction to VIPER

VIPER is a design pattern mostly used to develop iOS applications. It stands for View, Interactor, Presenter, Entity, and Router. VIPER splits the app's logic into distinct responsibilities, which makes the code more modular and easier to test.

Components of VIPER

Let's break down each component of VIPER:

View

The View displays what it is told to by the Presenter and relays user input back to the Presenter.

Interactor

The Interactor contains the business logic as specified by the use case.

Presenter

The Presenter contains the presentation logic and interacts with both the Interactor and the View.

Entity

The Entity contains basic model objects used by the Interactor.

Router

The Router handles navigation logic for the app.

Setting Up VIPER

To set up VIPER, you'll need to create a module for each feature. Each module will have its own set of components (View, Interactor, Presenter, Entity, Router).

Example folder structure:

FeatureModule/
    ├── Entity/
    ├── Interactor/
    ├── Presenter/
    ├── Router/
    └── View/
                    

Implementing VIPER

Let's implement a simple VIPER module for a "Login" feature.

Step 1: Create the Entities

Entities are simple model objects. For example, a User entity:

User.swift
struct User {
    let username: String
    let password: String
}
                    

Step 2: Create the Interactor

The Interactor contains the business logic. For example:

LoginInteractor.swift
protocol LoginInteractorProtocol {
    func login(username: String, password: String)
}

class LoginInteractor: LoginInteractorProtocol {
    var presenter: LoginPresenterProtocol?
    
    func login(username: String, password: String) {
        // Business logic for login
        let user = User(username: username, password: password)
        presenter?.loginSucceeded(user: user)
    }
}
                    

Step 3: Create the Presenter

The Presenter contains the presentation logic. For example:

LoginPresenter.swift
protocol LoginPresenterProtocol {
    func loginSucceeded(user: User)
    func loginFailed()
}

class LoginPresenter: LoginPresenterProtocol {
    var view: LoginViewProtocol?
    var interactor: LoginInteractorProtocol?
    var router: LoginRouterProtocol?
    
    func login(username: String, password: String) {
        interactor?.login(username: username, password: password)
    }
    
    func loginSucceeded(user: User) {
        view?.showSuccess(user: user)
    }
    
    func loginFailed() {
        view?.showError()
    }
}
                    

Step 4: Create the View

The View displays what it is told to by the Presenter and relays user input back to the Presenter. For example:

LoginView.swift
protocol LoginViewProtocol {
    func showSuccess(user: User)
    func showError()
}

class LoginViewController: UIViewController, LoginViewProtocol {
    var presenter: LoginPresenterProtocol?
    
    // UI components
    let usernameTextField = UITextField()
    let passwordTextField = UITextField()
    let loginButton = UIButton()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Setup UI and actions
        loginButton.addTarget(self, action: #selector(loginButtonTapped), for: .touchUpInside)
    }
    
    @objc func loginButtonTapped() {
        guard let username = usernameTextField.text, let password = passwordTextField.text else { return }
        presenter?.login(username: username, password: password)
    }
    
    func showSuccess(user: User) {
        // Show success message
    }
    
    func showError() {
        // Show error message
    }
}
                    

Step 5: Create the Router

The Router handles navigation logic. For example:

LoginRouter.swift
protocol LoginRouterProtocol {
    static func createLoginModule() -> UIViewController
}

class LoginRouter: LoginRouterProtocol {
    static func createLoginModule() -> UIViewController {
        let view = LoginViewController()
        let interactor = LoginInteractor()
        let presenter = LoginPresenter()
        let router = LoginRouter()
        
        view.presenter = presenter
        presenter.view = view
        presenter.interactor = interactor
        presenter.router = router
        interactor.presenter = presenter
        
        return view
    }
}
                    

Conclusion

In this tutorial, we covered the basics of the VIPER architecture pattern for iOS development. We created a simple "Login" module to demonstrate how to implement each component of VIPER. By using VIPER, you can create modular, testable, and maintainable code for your iOS applications.