Few patterns in iOS architecture inspire opinions as divided as VIPER.
Some call it “the answer for large-team collaboration”; others call it “boilerplate hell.” Several large service apps adopted VIPER or variants, then moved to lighter structures a few years later.
Today, we’ll summarize what VIPER aimed to solve—and why the cost was so high.
VIPER has five pieces
VIPER splits one screen into five roles. The name itself comes from their initials.
- View: Displays the screen, including the view controller. It only “draws.”
- Interactor: Business logic. Fetches data and applies rules.
- Presenter: Mediates between View and Interactor. Formats data for display.
- Entity: Pure data model.
- Router (Wireframe): Handles navigation.
It splits the work once done by one view controller in MVC (Model-View-Controller) into four parts, then extracts navigation into a separate piece (Router). Every responsibility of the Massive View Controller from part 1 gets its own dedicated place.
The core rule is a strict, nearly unidirectional reference relationship. View knows only Presenter; Presenter knows Interactor and Router; Interactor touches only Entity. Each boundary is defined by a protocol, so any piece can be swapped for a mock.
What improves?
There are clear situations where this structure shines.
First, you can push test coverage to the limit. Because every boundary is a protocol, Interactor, Presenter, and Router can each be tested in isolation.
Second, it simplifies division of labor on large teams. Every screen has the same structure, making file organization predictable. That uniformity genuinely helps when dozens of people touch one codebase.
Third, it fits feature-based modularization well. Since each screen is a self-contained set of five pieces, extracting feature modules is easier. Uber’s RIBs, inspired by VIPER, pushes this idea to the extreme: it splits the app into a tree by business-logic units rather than Views.
So why did everyone leave?
The problem is cost.
Boilerplate is overwhelming. Even a screen with one button creates six or seven files: View, Interactor, Presenter, Entity, Router, and the protocols between them. The complaint that “changing one label’s text takes three files” is well founded.
Even simple screens are forced to carry the same weight. A static settings screen and a complex feed screen both get five pieces. Structural weight does not scale with screen complexity.
The learning curve and onboarding cost are also substantial. It takes time for newcomers to follow data traveling View → Presenter → Interactor → Presenter → View.
The final blow was the arrival of SwiftUI. VIPER emerged from a UIKit-era concern: removing responsibilities from view controllers. In SwiftUI, View is already lightweight and navigation works differently, making pieces like Router feel awkward. The underlying problem changed.
So did VIPER fail?
That’s hard to say. VIPER’s legacy is embedded in today’s standard practices.
- Move navigation into a dedicated object → established as the Coordinator pattern
- Separate business logic from presentation → established as UseCase/Repository layers
- Define boundaries with protocols → established as dependency injection and testing practices
Fewer teams use all five VIPER pieces together, but the problems those pieces addressed—and their solutions—survived. Today’s approach is closer to choosing only the pieces you need.
Summary
- VIPER splits one screen into five pieces—View, Interactor, Presenter, Entity, and Router—and defines their boundaries with protocols.
- Testability and consistency across large teams are strengths, but the boilerplate cost is high: six or seven files per screen.
- As the underlying problem changed in the SwiftUI era, fewer teams use VIPER in its original form.
- Its legacy survives in standard practices such as Router→Coordinator and Interactor→UseCase.
Next time, we’ll cover the most widespread part of that legacy: what UseCase and Repository in clean architecture actually do on iOS.

![Cover image for [iOS Architecture #5] Why iOS VIPER Fell Out of Favor (RIBs)](/assets/images/posts/ef088d05-20c3-46e5-95b6-d23a695099e9/1.jpg)