MVC vs MVVM on iOS_ Key Differences With Examples
MVC vs MVVM on iOS_ Key Differences With Examples
Examples
Model-View-Controller (MVC) and Model-View-View Model (MVVM) are common software
patterns to help Swift developers build diverse, useful mobile applications. Learning the key
differences between the systems can help you find a better fit for your next project.
During the development of a modern iOS app, you need to select the proper architectural
pattern for the project and end user. The choice should be based on many factors, such as
expected app complexity, the experience of the team working on it, or the deadline for
implementation.
Before you choose a pattern, you’ll need to understand how they work, as well as what
problems they address and, in some cases, create. We can start by comparing two of the
most common mobile architectural patterns in the iOS environment: the
Model-View-Controller (MVC) pattern used by Apple together with third-party developers and
the Model-View-View Model (MVVM) originating from Microsoft's ecosystem.
The MVC pattern divides the responsibilities of an iOS application into different sectors that
serve their purpose. The MVC separates the business and operations side of the application
from the presentation layer while taking a middleman, known as the controller object, to
facilitate interactions between the Model and View, including retrieving data from the
database, manipulating it and either sending it back to the database or using it for rendering.
MVC Pattern
First of all, let’s take a look at the three layers that organize code in the
Model-View-Controller pattern:
● Model – is responsible for storing the data but should not manipulate it for the View’s
needs, as it is not aware in any way of the View. The model data is crucial as it is
used to create views that accurately represent the output to the user, including
various customer views with UI components.
● View – has two responsibilities: it takes care of presenting the data to the user and
receives the actions made by the user. It is not aware in any way of the Model – it is
updated with processed data by its owner. Because of this characteristic, View
should be devoid of any business logic.
● Controller – owns and communicates with the View and Model layers. It’s responsible
for updating the Model and the View with processed data from the Model. In the
simplest setup, Controller is usually set as a delegate to the View or it sets up proper
callbacks for the View to be able to update the Model and View based on user
actions.
MVC Advantages
The MVC design pattern provides the following advantages:
● Simplicity and ease of use. Due to the small count of simply defined components, it
is hard to find a pattern that would be more straightforward to introduce and maintain
than MVC.
● Clear separation of concerns. It is obvious what should be part of either the View or
Model.
● Reusability. Both View and Model are not tightly coupled with other components, so
it is easy to reuse them.
● Vast Learning Resources. It is one of the most common patterns. It was the most
frequently used in the early days of iOS development. It is widely understood by iOS
developers, and many learning resources regarding its usage are easily accessible.
MVC Disadvantages
While having strong arguments for implementation, the MVC pattern could also cause the
following issues during the development process:
● Controller is kind of a catch-all object here. If a given task does not belong to the
View or the Model, it usually ends up being implemented in the Controller, causing it
to become a large and complex object. This problem is frequently referred to as
Massive View Controller or Fat View Controller.
● To ensure the quality of the code, at least the business logic should be covered with
unit tests. In this pattern, this logic is placed in Controller – a complicated object
tightly coupled with both View and Model. This complexity significantly hinders
effective unit testing, making it very hard to write proper tests that can ensure code
reliability and performance.
● Direct result of those two drawbacks is reduced testability of this pattern. As the
Controllers grow in size and complexity, they cause difficulty in covering the app with
sufficient unit tests, along with problems in both maintaining and developing the
application.
MVVM Pattern
MVVM, short for Model-View-ViewModel (MVVM), is an architecture pattern that enhances
the separation of the graphical user interface from the business logic or back-end logic.
Similarly to MVC, this pattern divides the application into the model and view components.
However, unlike MVC where the controller mediates between the view and model, in MVVM,
this role is fulfilled by the ViewModel.
This leads to a cleaner separation of concerns, with the ViewModel acting as the mediator
and housing the business logic code that is separated from the view. The MVVM design
pattern offers several advantages over other patterns, such as MVC and MVVM, by
providing a more efficient way to build interactive applications.
MVVM Pattern
To address the problems mentioned above, MVVM introduces one additional layer to the
MVC setup. It is called View Model, and it replaces C with VM in the MVVM (even though
Controllers are still present in this pattern). Please note that the Model and the View have
the same responsibilities as in MVC.
● Model – is responsible for storing the data but should not manipulate it for the View’s
needs as it is not in any way aware of the View.
● View – has only two responsibilities: takes care of presenting the data to the user and
receives the actions made by the user. It is not aware in any way of the Model – it is
updated with processed data by its owner. Because of this characteristic, View
should be devoid of any business logic.
● View Model – is a new layer between the Model and the Controller. It owns the Model
and takes care of manipulating its data in a way that makes it ready to be displayed
by a simplified View. Additionally, it enables data binding, which facilitates two-way
communication between the view and the model, automating the propagation of
modifications and ensuring a clean separation of concerns.
MVVM Advantages
Considering the introduction of the View Model layer, here are the advantages of the MVVM
pattern.
Here are: Task (Model), TaskView, and TaskViewDelegate – those will be exactly the
same in both implementations. In the View, we are skipping the implementation of the init
and setting up the tap action handling. Note that this step is not related to or affected by the
architectural differences of the MVC or MVVM patterns.
struct Task {
var text: String
var isChecked: Bool
}
protocol TaskViewDelegate {
func didTap()
}
// Skipping init and setting up of the tap action that triggers didTap delegate method
Here is the implementation of MVC's controller. In this example, the controller is responsible
for owning the Model and transforming data into properties consumable by the TaskView.
This time, we are skipping the setting up of the view, as well as triggering the initial update;
this part will be the same in both architectural approaches.
func didTap() {
task.isChecked.toggle()
updateView()
}
func updateView() {
let image = UIImage(named: task.isChecked ? "checkedTaskIcon" :
"taskIcon")
let attributedText = NSAttributedString(string: task.text, attributes: attributes)
taskView.update(with: image, and: attributedText)
}
}
Now, let's see how we could implement a View Model that would own the Model, toggle its
isChecked value, and expose properties to the View that would be computed from Model's
data.
struct TaskViewModel {
var image: UIImage? {
UIImage(named: task.isChecked ? "checkedTaskIcon" : "taskIcon")
}
var attributedText: NSAttributedString {
NSAttributedString(string: task.text, attributes: attributes)
}
private let attributes = [NSAttributedString.Key: Any]() // Empty, for demo purposes
only
private var task: Task
init(task: Task) {
self.task = task
}
func toggleTask() {
task.isChecked.toggle()
}
}
Note that even though moving the business logic to the View Model increases the code-line
count, the result appears more readable since TaskViewModel has very obvious and
limited responsibilities. In addition to that, writing unit tests for it is simple. For example, this
is how a method testing the image property could look:
func testImage() {
// given
let task = Task(text: "Fixture Text", isChecked: true)
let sut = TaskViewModel(task: task)
// then
XCTAssertEqual(sut.image, UIImage(named: "checkedTaskIcon"))
}
Finally, let’s see how introducing the View Model will change the Controller in an MVVM
implementation.
func didTap() {
viewModel.toggle()
updateView()
}
func updateView() {
taskView.update(with: viewModel.image, and: viewModel.attributedText)
}
}
● Test the TaskView object to check the logic placed in the Controller. Since we would
be checking a system of two objects, this would actually be an integration test
instead of a unit test. A drawback here would be that to test all possible
configurations of view (n) and controller (m) we would need to write n*m instead of
n+m tests. It is easy to see that, in this scenario, the cost of maintaining tests grows
quickly alongside complexity.
● Change the implementation of the Controller by putting the data manipulation code
into two non-private properties. This would mean sacrificing the readability of the
class for the sake of its testability. While this practice may be acceptable in an easy
case, with growing complexity, it would be an increasingly difficult problem to cope
with.
Summary
While selecting the architecture pattern is one of the most important responsibilities of a
developer working on a mobile app, this decision has to be made considering the project's
specific needs.
On the other hand, if you want your app to be a little easier to expand and maintain when it
is getting more complicated, we have provided an example where MVVM streamlines the
testing process and divides the responsibilities. MVVM could be a good choice for your app
if you would like to avoid overgrown controller classes or facilitate the process of writing unit
tests.
Understanding the Differences: MVC vs. MVVM
When it comes to software architecture, choosing the right pattern is crucial for building
scalable, maintainable, and testable applications. Two popular patterns,
Model-View-Controller (MVC) and Model-View-View Model (MVVM), provide structure and
separation of concerns.
I will explore the differences between MVC and MVVM, highlighting their unique
characteristics, advantages, and use cases.
Separation of Concerns
View-Model Communication
In MVC, the View communicates directly with the Controller to handle user interactions and
updates. The Controller then interacts with the Model to retrieve or update data. The View
does not directly reference the Model.
In MVVM, the View communicates with the ViewModel through data binding. The ViewModel
exposes properties and commands that the View binds to. The ViewModel, in turn, interacts
with the Model to retrieve or update.
Data Binding
MVC typically does not have built-in data binding capabilities. The View relies on the
Controller to retrieve data from the Model and update the UI manually.
MVVM introduces powerful data binding capabilities. Data binding establishes a connection
between the View and the ViewModel, allowing automatic synchronisation of data between
them. When data changes in the ViewModel, the View is automatically updated, and user
interactions trigger commands in the ViewModel.
In Flutter, there are several popular state management frameworks that provide data binding
capabilities:
MVVM enhances testability with better separation of concerns. The ViewModel can be
tested independently of the View and the Model, as it does not have direct dependencies on
them. Unit testing the ViewModel becomes more manageable, resulting in more
comprehensive and focused tests.
MVVM provides enhanced flexibility through the use of data binding. The separation of the
View and ViewModel enables easier UI customization and reusability. Different Views can be
bound to the same ViewModel, or multiple ViewModels can be used with a single View.
Conclusion
MVC and MVVM are both effective architectural patterns that promote separation of
concerns. MVC provides a straightforward and widely adopted approach, while MVVM
introduces data binding and a clearer separation between the View and ViewModel.
The choice between MVC and MVVM depends on the specific requirements of the project,
the complexity of the UI, and the need for testability and flexibility. Understanding the
differences between these patterns helps developers make informed decisions and create
well-structured, maintainable applications. This blog will help you make the right decision.
Let’s dive into the MVC architecture and gain a deeper understanding of how it works 🔥
# M — Model
The “Model” is responsible for business logic, network calls, parse data, and so on. The
“Model” does not need to know about the UI if you in the “Model” use UI attributes it means
your architecture goes wrong.
# V — View
The ‘View’ is responsible for representing UI elements such as UILabel, UIView, UITextView,
and so on. It should not have knowledge of the ‘Model.’ Including business logic and
network calls within the ‘View’ indicates a problem in your architecture.
# C — Controller
The “Controller” acts as an intermediary between the “Model” and the “View”. It handles
🤷♂️
user input, communicates with the “Model” to fetch or update data, and updates the “View”
accordingly. You can see the above image
The MVVM architecture is quite similar to the MVC design pattern. While it shares many
similarities with MVC, MVVM is widely used in SwiftUI, and it’s especially beneficial when
working with the Combine framework.
# M — Model
The “Model” in MVVM is similar to the “Model” in MVC. It represents the data and business
logic of the application. It defines how data is structured and manipulated. In Swift, the
“Model” can be implemented using classes, structs, or enums.
# V — View
The “View” in MVVM is also similar to the “View” in MVC. It represents the only UI elements
and the “View” should only display data, and handle user interactions, without containing
application logic(business logic).
# VM — View-Model
The “ViewModel” acts as a mediator between the “Model” and the “View”. The “ViewModel”
is responsible for preparing and formatting data from the “Model” for presentation in the
“View”. “ViewModels” also handles user input and interactions. They contain the business
logic needed for specific views.
struct Task {
# ViewModel
class TaskListViewModel {
return tasks.count
return tasks[index]
tasks.append(newTask)
tasks[index].completed.toggle()
}
}
# View
import UIKit
super.viewDidLoad()
tableView.dataSource = self
viewModel.addTask(title: taskTitle)
taskTextField.text = ""
tableView.reloadData()
return viewModel.taskCount
}
cell.textLabel?.text = task.title
return cell
1. Task represents the “Model”, which defines the structure of a task.
2. TaskListViewModel is the “ViewModel”, responsible for managing tasks, adding
tasks, and updating their completion status.
3. TaskListViewController is the “View”, which displays the list of tasks in a table view
and allows the user to add new tasks. It communicates with the ViewModel to
perform these tasks.
The MVP architecture is also similar to MVC architecture the same “Model” layer, “View”
layer, and additional “Presenter”. However, the MVP design pattern has one difference from
the MVC design pattern. Now the ViewController(Controller layer) is considered as a
view. which means it will include only the view-related code, nothing more and all logic will
be implemented in the presenter.
● View: The “View” includes both view and view controllers, taking care of setting up
the user interface and handling user interactions and all events.
● Presenter: The “Presenter” handles all the logic, such as responding to user actions
and updating the UI through the Protocols and Delegates. An important aspect is that
our presenter is UIKit-independent, making it well-isolated and easily testable.
● Model: The “Model” role will be exactly the same in MVC architecture.
struct Task {
# View
self.init()
self.presenter = presenter
configureView()
titleLabel.text = task.title
descriptionLabel.text = task.description
presenter.taskCompleted()
# Presenter
protocol TaskPresenterProtocol {
func taskCompleted()
init(task: Task) {
self.task = task
}
return task
func taskCompleted() {
● Task: The task represents the “Model”, which defines the structure of a task.
● TaskPresenter: The TaskPresenter is the “Presenter”, which manages the
interaction between the “Model” and the “View”. It provides methods to fetch task
data and mark tasks as completed.
● TaskViewController: The TaskViewController is the “View”, which displays the task
information and handles user interactions. It receives a TaskPresenterProtocol
instance and uses it to fetch and update task data.
Thank you for your attention while reading this article and I will be very happy if you
share your opinions about this article.
I hope to see you soon with your suggestions and problems please write to me on LinkedIn.
ARC —
https://medium.com/@knoo/arc-automatic-reference-counting-in-swift-e7ac473229cc
SOLID — https://medium.com/@knoo/solid-principles-in-swift-2324df4a814c
Linkedin — https://www.linkedin.com/in/knyaz-harutyunyan-1a3672235/
GitHub — https://github.com/Kno777
In this article I am trying to show you some basics about MVC and MVVM architecture with
example.
M stands for Model and in design architecture Model is used to just represent
the data.
2. View (V)
V stands for View. View is used to display the data (received from Model or
ViewModel). So basically XIB,Storyboard acts as a View.
3. Controller (C)
In this example,
UserViewController.swift — Controller_image1
UserViewController.swift — Controller_image2
We are receiving some data from web server ( see Controller_image2) in Controller class
and passes those data to our Model class ( see below Model_image3). And Model sends
structured data back to controller.
UserInfo.swift- Model_image3
So we can see that in Controller class, we are receiving data from server and then pass
that response to Model class and then Model class sends structured data to Controller
class back. Then Controller class sends that structured data to View class to display it. So
we can say that Controller acts as mediator between Model and View class.
Another thing you might be noticed in MVC, View class is not just
responsible to display data. it also performs some logic over the data and
then display it. See below highlighted code implemented in
UserInfoTbaleViewCell.swift — View_image4
you can see in above code, it first performs some logic (checking wether isAdmin property of
userInfo is true or false ) for contentView’s background color and then accordingly it sets the
background color.
So this is the main difference between MVC and MVVM, in MVVM “View
class” is responsible for just displaying the data, it never performs any
operation over data. To perform logic over data VM (View Model) class is
there.
While in MVVM one new class ViewModel is there, and there is a little change in View
class.
1. Controller class passes data (received from server) to Model class.
2. Model class returns structured data to Controller class.
3. Controller class passes structured data to ViewModel class.
4. ViewModel class performs logic over that data if needed and then sends back that
final data to Controller class.
5. Controller class passes final data to View class and finally View class displays that
data on the screen.
UserVIewModel.swift — ViewModel_image5
UserViewController.swift — Controller_image6
UserViewController.swift — Controller_image7
UserInfoTableViewCell.swift — View_image8
So this is the difference between MVC and MVVM. The example which I have used is so
simple, in real you can have complex project. But in this article I have tried to demonstrate
the difference between MVC and MVVM in a very simple way.
Each pattern has some pros and cons. So it is up to you which pattern you need to use as
per requirement.