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:
struct User { let username: String let password: String }
Step 2: Create the Interactor
The Interactor contains the business logic. For example:
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:
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:
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:
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.