iOS Architectural Patterns (MVC, MVVM, VIPER)

Updated Feb 19, 2023#ios#patterns#architectures

Each architecture has pros and cons, MVC is everywhere, MVVM is community favorite, and VIPER is unnecessary complicated.

Though these architectures all vary somewhat in their details, they are very similar. They all have the same objective, which is the separation of concerns. They all achieve this separation by dividing the software into layers.

There are a lot of aspects to consider when selecting an architecture for your next awesome iOS app. By separating into layers, you will create an app that is intrinsically testable, with all the benefits that implies.

MVC

This pattern separates the UI into the Model that represents the application state, the View, which in turn is composed of UI controls, and a Controller which handles user interactions and updates the model accordingly.

One big problem with the MVC pattern is that it’s quite confusing. The concepts look good, but often when people come to implement MVC, the seemingly circular relationships illustrated above result in the Model, View and Controller becoming a big, horrible mess.

MVVM

At the core of this pattern is the ViewModel, which is a special type of model that represents the UI state of the app. It contains properties that detail the state of each and every UI control. For example, the current text for a text field, or whether a specific button is enabled. It also exposes the actions the view can perform, like button taps or gestures.

The relationships between the three components of the MVVM pattern are simpler than the MVC equivalents, following these strict rules:

  • View has a reference to the ViewModel, but not vice-versa.
  • View has no reference to the Model or vice-versa.
  • ViewModel has a reference to the Model, but not vice-versa.

If you break any above rules, you’re doing MVVM wrong. A couple of immediate advantages of this pattern are:

  • All your UI logic resides within the ViewModel, resulting in a very lightweight view.
  • You can run your entire app without the View which greatly enhances its testability.

MVVM has become popular over recent years when Apple release Combine, a framework that provides logical streams of data which can emit values over time. Alongside with SwiftUI and its bindings to provide a declarative way of creating user interfaces.

Once you are on the ViewModel side, using Combine becomes the natural choice. It allows you to cleanly define a chain that starts in your UI, way down to a network call.

VIPER

VIPER is an architectural pattern like MVC or MVVM, but it separates the code further by single responsibility. Apple-style MVC motivates developers to put all logic into a UIViewController subclass. VIPER, like MVVM before it, seeks to fix this problem.

  • View is the user interface, corresponds to a SwiftUI view.
  • Interactor is a class that mediates between the presenter and the data, takes direction from the presenter.
  • Presenter directs data between the view and interactor, taking user actions and calling to router to move the user between views.
  • Entity represents application data.
  • Router handles navigation between screens.