The 7 Most Popular iOS Architecture Patterns Explained

Architecture patterns are a heavily debated topic among software engineers.

Ultimately there is no right answer for every project and it depends on your needs. I did some research on the 7 most popular architecture design patterns in iOS and will share them will you in this article.

The 7 most popular iOS architecture patterns are:

  • Model-View-Controller (MVC)
  • Model-View-ViewModel (MVVM)
  • Model-View-Controller-ViewState
  • ModelAdapter-ViewBinder
  • The Elm Architecture
  • VIPER
  • Component-based architecture

What is Model-View-Controller (MVC)?

Model-view-controller is the most popular design architecture in-app architecture design. It is the one Apple recommends and it’s easy to understand and use. In most code examples on the official Apple or Swift websites, applications are built using the MVC architecture. This is the default application architecture pattern used in all iOS, MacOS, and watchOS projects.

zero to app store

Model View Controller Pattern

The controller in a model-view-controller architecture is responsible for many things. It receives all the view actions, handles all user interaction logic, dispatches changes to the model, receives changes from the model and lastly applies those changes to the view.

This results in the controller files being very large and difficult to break apart in the MVC model. Many developers think that is a downside of using a model-view-controller architecture. There’s a joke that MVC actually stands for Massive View Controller :).

MVC Initialization

The application starts by initializing the top-level view controllers. These view controllers then load and configure the views with the data from the model. The controller can either create its own models explicitly or access them through a singleton. If multiple controllers need to access the same model, a UIDocument can be used to make this easier.

MVC Model Updates

In this architecture, the controller will receive updates either through delegates or user interactions with the view. Views have no knowledge about their controllers. When an update or change occurs, the view controller will update the model or modify its own internal state.

MVC View Changes

View changes occur after the controller has updated the model. After the controller has updated the model, another function in the view controller is listening to changes to the model. When changes are detected to the view model, the controller will make the appropriate changes to the view itself. This is a one-directional flow of data which makes it easier to debug and manage this code later on.

  1. View actions and delegates calls are saved as model changes
  2. View controller listens to model changes
  3. View controller updates view

View State

View states are stored either as properties of the view or the view controller. If a view action doesn’t change a model property, it can be stored on the view or the controller and doesn’t need to update the model.

MVC Testability

Sadly, in an MVC model, the view controller is extremely tightly coupled with the rest of the application. The lack of boundaries and compartmentalization makes it more difficult to test.

Integration tests are typically used in MVC models as these are the easiest tests to write for this type of architecture.

What is Model-View-ViewModel (MVVM)?

Model-View-ViewModel separates a lot of the logic the view controller had to handle into a separate component called the view model. The view model is responsible for all the presentation logic. It is essentially an augmented version of the MVC architecture. This lets our view controllers be smaller and more manageable. Due to its similarity with Model-View-Controller, MVVM can be easily incorporated into an existing MVC app.

zero to app store

MVVM Initialization

Model-View-ViewModel initialization is very similar to MVC. A difference is that the view controller now also initializes a view model. The view controller then binds each view to relevant properties in the view model.

The models are also no longer directly owned by the view controllers and instead owned by the view models.

MVVM Model Updates

The view controller receives updates or changes from user interactions or delegate calls, just like the MVC pattern. However, instead of the view controller changing its state or the model, it calls a function of the view model. The view model then either changes its internal presentation state or makes changes to the model.

MVVM View Changes

In MVVM, the view controller does not observe the model. Instead, the view-model is responsible for listening to changes to the model. The view model handles model changes and updates its own internal state. The view controller is subscribed to the changes in the view model and will update the view accordingly when it detects those changes. Typically these are done using a reactive programming framework or other observation mechanism.

MVVM View State

View states are either properties of the view themselves or stored in the view model. The view controller does not store any view state, unlike MVC.

MVVM Testability

Testability is a little easier in MVVM than MVC because the view model is decoupled from the view controller. This allows you to perform interface testing as opposed to integration testing.

Interface tests are a lot easier to write and maintain as you don’t need to setup a large amount of components to test a certain piece of logic.

What is Model-View-Controller-ViewState?

The model-view-controller-viewstate architecture aims to build on MVC. It is similar to the MVVM pattern as well. However, the view controller still determines all model changes, unlike the view model in MVVM. It aims to separate out view state and make it more manageable.

zero to app store

MVCVS Initialization

The view controller now has to listen to both the view state and the model. This observation can be set through reactive programming. This means more notification work will be done through the view controller.

MVCVS Model Updates

When a change comes in, the view controller updates the view state or the document model. All changes to the view hierarchy happens through either the view state or the document model.

MVCVS View Changes

The view controller observes the view state or the document view model and changes to the view occur through these observations.

MVCVS View State

The view state is explicitly separate from the view controller. The controller updates the view state and listens to changes from it.

MVCVS Testability

For this architecture, testability is done via integration tests. However, it is slightly better than MVC as you can test the logic to the document model and the view model separately.

What is ModelAdapter-ViewBinder?

ModelAdapter-ViewBinder is a new, more experimental design pattern. It aims to get rid of the controller entirely and instead replace it with view binders and model adapters.

View binders are a wrapper class around the view class which provides bindings for changing the view with new information or emitting events based on user interaction.

View binders have dynamic bindings but they are immutable. This makes this architecture declarative. You define the bindings to the view in the view binder once and the bindings handle the data flow.

Model adapters are wrappers around the model can be described as reducers. Just like the view binder, it has a two-way binding that allows it to send events and receive updates.

zero to app store

MAVB Initialization

Modal adapters and view binders are created before any view is made. Views are then created and bound to their respective view binders.

MAVB Model Updates

When the view emits actions, the view binder is notified. The view binder will then subsequently notify the model adapter. The model adapter will reduce this message and make the appropriate changes to the model.

MAVB View Changes

When the model changes, the model adapter will emit a message to the view binder. The view binder will handle this message and the view will change accordingly.

MAVB View State

View state is stored in the model. View state data flows the same way as changes to the model.

MAVB Testability

In this architecture we test our code by testing the view binders. The view binders can be tested to verify they behave correctly during a certain user interaction or when there is an update to the model.

What is The Elm Architecture?

The Elm Architecture, also known as TEA, is quite different from the model- x design patterns. In TEA, the model and view state are a single object. All updates to the model and view state are sent as messages to this single state object and are handled by methods called reducers.

Every change to the state results in a new virtual view hierarchy. This is a set of structs describing how the view should look. The benefit of this is that our views can be described as pure functions. The view is always calculated from the state object.

The way events flow in this architecture is unidirectional. If you’re familiar with Facebook’s Flux or Redux, it’s a very similar pattern.

zero to app store

Elm Initialization

The state is created on startup. The virtual view hierarchy is then created from the state and the runtime updates the real view based on differences between the real view and the virtual view hierarchy.

Elm Model Updates

Virtual views can send messages when user interaction occurs. These are then passed to the state model and can update the store.

Elm View Changes

All view changes must happen as changes to the state object.

Elm View State

View state is a part of the state model.

Elm Testability

In the elm architecture, you can just test that the state model produces the correct virtual view hierarchy when the state changes. Since views can be produced from pure functions, this makes testing simple. It allows us to test each part of the view hierarchy individually. This is one of the main benefits of using The Elm Architecture.

What is VIPER?

VIPER is an adaption of Clean Architecture for iOS applications. It stands for View, Interactor, Presenter, Entity, and Routing. VIPER is designed to build components around different user cases.

VIPER is a hard pattern to start with as it requires many different components. Teams that use VIPER almost always use code generators as the amount of boiler plate code required to use this pattern is quite large.

It’s an architecture that has many different components so let’s break it down.

zero to app store

View

The view displays what the presenter tells it to. It sends messages back to the presenter based on user interaction.

Interactor

The interactor contains business logic on a per use-case basis.

Presenter

This contains the view logic and view state. It changes the view based on messages sent from the interactor.

Entity

Entities are basic models that the interactor uses.

Routing

The router controls which view will be displayed and what the next view will be.

What is component-based architecture?

Component-based architecture is a newer to mobile app development. This has become very popular with frameworks such as React Native. Flutter also has a similar design with its use of widgets.

It will be interesting to see if this architecture gains more traction, especially in the Swift or native iOS development world.

zero to app store

What’s the easiest design pattern for iOS? Model-View-Controller is the best pattern for beginners to learn. Apple writes a lot of their learning material using this pattern and theres a strong community behind it.

My view controllers are too big, how do I make it more manageable? Consider using a design pattern such as model-view-view-model.

If you liked this post and want to learn more, check out The Complete iOS Developer Bootcamp. Speed up your learning curve - hundreds of students have already joined. Thanks for reading!

Eddy Chung

I teach iOS development on ZeroToAppStore.com.

Similar Posts