What is Massive View Controller and How to avoid it in Swift

Mehdi Mirzaie
Divar Mobile Engineering
4 min readSep 2, 2020

--

In this story, we will explain MassiveViewController and suggest three approaches that can avoid it. We are focusing on MVC architect in this story however you can benefit from these ways even if you use other architectures like MVVM, VIPER, and MVP. I assume that you already have some knowledge about MVC architecture and how to implement this architecture in Swift. If you are not familiar with MVC I suggest you read the following tutorial from Raywenderlich.

What is Massive View Controller?

One of the known issues of MVC architecture in iOS Development is the Massive View Controller.

UIViewController is responsible for two fundamental duty

  • presenting data to the user
  • handling user interaction

Well, it seems like simple responsibilities but why we keep saying MASSIVE ViewContoller?

The answer is they are simple as long as we keep the view small, if the Viewcontroller gets complicated then we end up a file with more than 500 or 600 lines of code.

Let us break those two responsibilities into more detailed

  • Implementing Datasource and delegates of UITableView or UICollectionView
  • Handling IBActions and IBOutlets
  • Handling segues ( if you are using storyboards)
  • Navigation Flow
  • Layout
  • Data Fetching
  • Binding Model-View

So Massive View Controller is :

Because view controllers in iOS carry many responsibilities and are closely related to the app screens, a lot of code ends up being written in them because it is just easier and faster that way.

So how can we fix that? Switching the architecture to Viper, MVP or MVVM would help us a little with that but what if we don’t have enough time and resources.

For Better understanding, we created a simple application that faced MassiveViewController and now we go step by step to fix it.

The main screen of the application consists of a Collection view that shows dog images and a TableView that show dog image and its title.

Users can tap on a dog cell to see a Detail screen.

So our ViewController will implement the layout of UICollectionView and UITableView, Implement DataSource and Delegate of UICollectionView and UITableView and Handling navigation to DetailViewController.

That is a lot of works to do then it is against SRP (Single Responsibility Principle).

Let’s fix it.

There are three approaches that you can use to fix the MassvieViewController

1-Child View Controller

2-Coordinator Pattern

3-Separate Datasources

Child View Controller

Just like how a UIView can be added to another UIView to form a hierarchy, a view controller can become the child of another view controller. That enables us to compose our UI from multiple building blocks, which can lead to smaller view controller implementations that are easier to reuse

We can break our HomeViewController into two ViewController.

The first one for Dog’s image that contains a UICollectionView and second one for Dog’s list that contains a UITableView.

After creating child view controllers we can simply add them to our HomeViewController

Coordinator pattern

The coordinator is a pattern presented by Soroush Khanlou and it’s responsible for handling navigation flow for the app.

The benefits of using the coordinator are listed below

  • Removing navigation flow from UIViewController to separated class
  • Having a better Encapsulation since the view controller doesn’t need to know any information about other view controllers
  • More reusability of the view controller

For adding Coordinator to the project first we need to create a protocol

You may want to add Stop method and ChildCoordinator to have more power in your Coordinator

Then we should implement MainCoordinator and use the Start() method in AppDelegate

Now coordinator is ready to add navigation methods.

For using coordinator we need to just call methods of MainCoordinator in Home view controller.

Make sure to mark coordinator instance as optional in case that a ViewController doesn’t need a coordinator

This how you should use the coordinator in your app. It may seem simple in this sample but the coordinator will do a lot when your app has a lot of navigations.

if you want to read more about the Coordinator read below

Separate Datasources

When you are adding UITableView, UICollectionView, or any other component which needs a DataSource or Delegation implementation you can simply separate them in a file and construct them with necessary data.

Note: Remember to inherit your DataSource class from NSObject so you can implement protocol stubs.

So before separating DataSource and Delegate our view controller is like this:

after implementing DataSoruce in sperate class our view controller change to this:

DogsTableDataSource is a subclass of NSObject that adopted to UITableViewDataSource and UITableViewDelegate protocols

You can have the completed source code in Github Repository

This repository has two branches:

Master: source code with MassiveViewController

Refactoring: source code with Coordinator, ChildViewControllers to fix MassiveViewController

Checkout between those two branches to see the difference.

Consultation:

Massive View Controller happens because ViewController has too many responsibilities. By using ChildViewControllers, Coordinators, and separating DataSources and Delegates not only we can fix the Massive View Controller but also having more testable and reusable code and follow the Single Responsibility Principle.

--

--