View Interactor Presenter Entity Router (VIPER) | DaddyCoding - Learn Swift, SwiftUI, iOS, RxSwift Programming

Ask questions Research chat →

https://daddycoding.com/2021/06/28/view-interactor-presenter-entity-router-viper/ · scraped

programming

Attachments

Scraped Content

— 1429 words · 2026-02-14 17:39:49 UTC ·

Excerpt

View Interactor Presenter Entity Router (VIPER) The View Interactor Presenter Entity Router (VIPER) is an architecture pattern that separates objects into five distinct types mainly made up of View, Interactor, Presenter, Entity and Router. ![](https://prod-files-secure.s3.us-west-2.amazonaws.com/871f1661-80b8-4d0c-ac3b-2adfc6ff4c66/e870dc63-1282-432d-99b4-c51904d0c0cc/1DvjrnzCVOWG5FrUEEet5mA.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466VMYTJDKI%2F20260214%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20260214T173949Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEEEaCXVzLXdlc3QtMiJHMEUCIEjN8F9wwMV8a4I%2BV2wxrYiyvh%2Fbge%2FQVtS0XsbHC5PyAiEAlY%2BIxi9iQJs0tZcFOIPUGfJhl7q4LU%2BVaHRGnTLVdpIq%2FwMIChAAGgw2Mzc0MjMxODM4MDUiDKCdiDgUWfPXcnx42SrcA9eP1M7PrVPg5qceUDy8ylYXH7X%2Bpf3dKnfOekU6XQ4TRcgIaBRy2E4DQothJ98eQXDAn6LvYOpWQOZUTuF%2FRepRFmjJSkejOzg7lNXypJ1t8%2FtCOrMHOhGt0xWTcP4BZTDhULyFAafV4KVPl%2BPpi%2FLHem1Fpb9MV5ayIT2sXbfsi0Zz
View Interactor Presenter Entity Router (VIPER) The View Interactor Presenter Entity Router (VIPER) is an architecture pattern that separates objects into five distinct types mainly made up of View, Interactor, Presenter, Entity and Router. ![](https://prod-files-secure.s3.us-west-2.amazonaws.com/871f1661-80b8-4d0c-ac3b-2adfc6ff4c66/e870dc63-1282-432d-99b4-c51904d0c0cc/1DvjrnzCVOWG5FrUEEet5mA.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466VMYTJDKI%2F20260214%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20260214T173949Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEEEaCXVzLXdlc3QtMiJHMEUCIEjN8F9wwMV8a4I%2BV2wxrYiyvh%2Fbge%2FQVtS0XsbHC5PyAiEAlY%2BIxi9iQJs0tZcFOIPUGfJhl7q4LU%2BVaHRGnTLVdpIq%2FwMIChAAGgw2Mzc0MjMxODM4MDUiDKCdiDgUWfPXcnx42SrcA9eP1M7PrVPg5qceUDy8ylYXH7X%2Bpf3dKnfOekU6XQ4TRcgIaBRy2E4DQothJ98eQXDAn6LvYOpWQOZUTuF%2FRepRFmjJSkejOzg7lNXypJ1t8%2FtCOrMHOhGt0xWTcP4BZTDhULyFAafV4KVPl%2BPpi%2FLHem1Fpb9MV5ayIT2sXbfsi0ZzqXlGbZ6Y%2F%2FKRzWUeC5gD40KL0zEE8xcWIDiMi%2B2Kx7%2FTv%2BSArSICxz8nvhQOTsjZy5hct2jzPlRT6eb7%2B3cazi%2FD05ac1fHHlCr%2B44O0nEKtqW4ybX2DNaNq%2FmHTbJt5Qlcl1zpmxSavDP1e3q4RxKRm%2Be1KqqU9535iKvWRhMfjdbbH3Sgkt0Grkxtbvnm8E1ExFcnagbfTS7JcKbDHj%2BTOA14D45jWEOGQOn07JMzgAKblPIuA%2FAmsTvAo5SkK9lIIJvCe1av06Gyac5J6wUXG08%2Ffxlp2YQtH4%2FQErvTOHvKr5tHq6oQqItXm8SxLUfNvQlUg958gVofWdBLPIdWoJXcZwGEVdOCxenIdMGQeq%2BBEPvDa07bOYXK6GTkDO8bJ1tgdLnlRghS81Dg%2BiiyG1x0ardAV7zZguIdMHxaR2VCCF8MI0rZoQ%2FzKXYO80SVzDdCqmSeiMJPSwswGOqUBqJdzf40py66X6Lfld1OgU0IeWNqISR%2BcsYHNJSbt8e813zAEPgGgmXJfsA5NmjOEKf3TvUK3rdkVykW4M9sHZRSmIhGAAWiHK0U7P3y2l5L0TjXP3HCM6LX1BTpepQPjNFX%2BhhexQNn3thK21Rr%2BaDzqTa3FHnTMYNJxdx8nrNY4NjJHJdh3JfL78LQwbcqp0gFlYG2MrFMI%2FZ3ekwbukLpNPb3m&X-Amz-Signature=b7b8df7d007d0449b81f5502a455a58757ae61a4bcb4a96fbbcc35ddccb48dee&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject) VIPER divides the logical structure into distinct layer of responsiblities which then isolate the app’s dependencies. With that you, there are multiple components which play different role here: - View delegate user interaction to Presenter. - Interactor mediates between the Presenter and data where it takes instruction from the Presenter. - Entity aka as Model holds the application data. - Presenter mediates between View and Interactor and use Router to move to different screens. - Router handles navigation between screen. VIPER focuses heavily on Presenter where its sole purpose is the View and user action whereas, Interactor focuses on manipulating the data. # When should you use it? VIPER becomes the preference for most big projects. However, it could be really difficult to understand for beginners due to the large number of components being used. # Implementing VIPER Architecture Pattern Before proceeding, the article will take into account that you know how to navigate around Xcode and have at least basic knowledge in Swift. For this article, you will learn how to implement VIPER architecture pattern and you will be building a bucket list app. You can try migrating your code from MVC to VIPER. And for this, you will use the code from the MVC. # Organising the File Structures You will see many different ways of organising the file structures but as a starter, this is how it will look like. Following the architecture pattern, the files are stored according to its responsibilities. As the files grow larger and larger, know that there isn’t a fixed way of structuring the files. The files should be very easy for you to navigate around. # PROTOCOLS There are multiple protocols where you will need to create to better structure the VIPER architecture pattern. First, you will create HomeViewToPresenterProtocol and this will allow View to communicate with the Presenter. With that being said, 1. HomeViewController will have a local variable of type HomeViewToPresenterProtocol 2. HomePresenter will need to conform HomeViewToPresenterProtocol. You may quickly join to the View section below to have a detailed code changes. ```plain text protocol HomeViewToPresenterProtocol { var view: HomePresenterToViewProtocol? { get set } var interactor: HomePresenterToInteractorProtocol? { get set } var router: HomeRouterProtocol? { get set } func updateView() func addBucketList(_ bucketList: String?) func updateBucketList(_ bucketList: BucketList) func getBucketListCount() -> Int? func getBucketList(_ index: Int) -> BucketList? } ``` Next, you will need to create HomeInteractorToPresenterProtocol which allows the Interactor to communicate with the Presenter. With that being said, 1. HomeInteractor will contain a variable with the type of HomeInteractorToPresenterProtocol. 2. HomePresenter will conform HomeInteractorToPresenterProtocol. ```plain text protocol HomeInteractorToPresenterProtocol: class { func fetchBucketListSuccess() func fetchBucketListFail() } ``` Next, you will need to create HomePresenterToInteractorProtocol which allows the Presenter to communicate with the Interactor. With that being said, 1. HomePresenter will have a local variable with the type of HomePresenterToInteractorProtocol. 2. HomePresenter will conform to HomePresenterToInteractorProtocol. ```plain text protocol HomePresenterToInteractorProtocol { var presenter: HomeInteractorToPresenterProtocol? { get set } var bucketLists: [BucketList]? { get } func fetchBucketList() func addBucketList(_ bucketList: String?) func updateBucketList(_ bucketList: BucketList) } ``` Next, you will create HomePresenterToViewProtocol which allow the Presenter to communicate with View. With that being said, 1. HomePresenter will have a local variable of HomePresenterToViewProtocol type. 2. HomeViewController will conform to HomePresenterToViewProtocol. ```plain text protocol HomePresenterToViewProtocol { func reloadView() } ``` Lastly, you will create HomeRouterProtocol which is where you will build your module. This will be conform by HomeRouter only. ```plain text protocol HomeRouterProtocol: class { static func createModule() -> UIViewController } ``` # VIEW You will start it off with HomeViewController where you will need to some refactoring, assuming that you have already created a local variable following the instructions above. ```plain text var presenter: HomeViewToPresenterProtocol? ``` Next, within the configureView, you will instantiate the view first. ```plain text presenter?.updateView() ``` Some of the places where you will need to quickly refactors to use Presenter are: 1. Adding bucket lists using the Presenter. ```plain text let okAction = UIAlertAction(title: "Ok", style: .default, handler: { [weak self] (_) in guard let strongSelf = self else { return } strongSelf.presenter?.addBucketList(alert.textFields?.first?.text) }) alert.addAction(okAction) ``` 1. Updating the bucket lists using the Presenter. ```plain text private func updateBucketList(_ bucketList: BucketList) { presenter?.updateBucketList(bucketList) } ``` 1. Getting number of rows in section for table view through the Presenter. ```plain text func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return presenter?.getBucketListCount() ?? 0 } ``` 1. Within cellForRowAt, you should now retrieve the bucket list from the Presenter. ```plain text let bucketList = presenter?.getBucketList(indexPath.row) ``` 1. Within didSelectRowAt, you will also need to retrieve the bucket list selected through Presenter. ```plain text func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if let bucketList = presenter?.getBucketList(indexPath.row) { let detailVC = DetailViewController(bucketList: bucketList) .. .. } ``` Lastly, you will need to conform HomePresenterToViewProtocol. This is where you will reload the table view everytime a new bucket list is either added or updated. ```plain text extension HomeViewController: HomePresenterToViewProtocol { func reloadView() { tableView.reloadData() } } ``` # Creating an Interactor You will need to create a new file called HomeInteractor where it conform to HomePresenterToInteractorProtocol. You will then be required to add all the codes related to the protocol. ```plain text class HomeInteractor: HomePresenterToInteractorProtocol { // 1 var presenter: HomeInteractorToPresenterProtocol? // 2 var bucketLists: [BucketList]? // 3 func fetchBucketList() { self.bucketLists = [] self.presenter?.fetchBucketListSuccess() } // 4 func addBucketList(_ bucketList: String?) { if let bucketListName = bucketList { let bucketList = BucketList(name: bucketListName, date: Date()) bucketLists?.append(bucketList) self.presenter?.fetchBucketListSuccess() } } // 5 func updateBucketList(_ bucketList: BucketList) { if let bucketListIndex = self.bucketLists?.firstIndex(where: { $0.name == bucketList.name }) { bucketLists?[bucketListIndex] = bucketList self.presenter?.fetchBucketListSuccess() } } } ``` 1. A reference to Presenter to be able to access some of the functions. 2. By default, the bucketLists is nil. 3. You need to call fetchBucketLists to instantiate it to be an empty array. This is used in HomeViewController. 4. The logic to add new bucket list and reload the table view. 5. The logic to modify the bucket list and reload the table view. # Creating a Presenter Presenter is a mediator where it will send the data to the neccessary component to either manipulate the data or update the UI. The Interactor plays a role here in manipulating the data executing the logic required. The View plays a role here in refreshing the UI to reflect the latest changes. ```plain text class HomePresenter: HomeViewToPresenterProtocol { var view: HomePresenterToViewProtocol? var interactor: HomePresenterToInteractorProtocol? var router: HomeRouterProtocol? func updateView() { interactor?.fetchBucketList() } func addBucketList(_ bucketList: String?) { interactor?.addBucketList(bucketList) } func updateBucketList(_ bucketList: BucketList) { interactor?.updateBucketList(bucketList) } func getBucketListCount() -> Int? { return interactor?.bucketLists?.count } func getBucketList(_ index: Int) -> BucketList? { return interactor?.bucketLists?[index] } } extension HomePresenter: HomeInteractorToPresenterProtocol { func fetchBucketListSuccess() { view?.reloadView() } func fetchBucketListFail() { view?.reloadView() } } ``` # Entity Entity is also known as Model and you probably should have known that our Entity is actually BucketList. ```plain text struct BucketList: Equatable { let name: String let date: Date var completed: Bool = false var givenUp: Bool = false } ``` # Create a Router Lastly, you will create a new file called HomeRouter which conform to HomeRouterProtocol. This is where the dependency is managed at one place and it makes it very easy to swap or modify the dependency. ```plain text class HomeRouter: HomeRouterProtocol { static func createModule() -> UIViewController { let view = HomeViewController() let presenter = HomePresenter() let interactor = HomeInteractor() let router = HomeRouter() view.presenter = presenter presenter.view = view presenter.router = router presenter.interactor = interactor interactor.presenter = presenter return view } } ``` This is being used inside AppDelegate where XIBs are being used rather than Storyboard. You may check out on one of my article on how to remove storyboard. # The Fruit of Your Labor # Conclusion You learned about the VIPER architecture pattern. Here are some key points: - VIPER consist of five components — View, Interactor, Presenter, Entity and Router. - VIPER focuses on the first SOLID Principle — Single Responsiblity Principle. - Presenter is the mediator and directs the information to either Interactor or Router. # Where to go From Here If you like what you read, please feel free to share it with others so that other may benefit from it as well. Stay tuned for the next part where you will learn how to use different architecture pattern.

Visibility

Visible to everyone

Reading Status

Related Bookmarks

My Note


Saved!

Annotations

Export as Markdown
+ Annotate selection

Add Annotation