MVC Composition (Part 2)
This is a small addition to my previous MVC-Composition post. I will show how to add an ActivityIndicator while data is loading from network in a MVC-Composed architecture.
The code for the following article can be found in this repository:
https://github.com/giln/MVC-Composition-Part2.git
We want to add a small activity indicator while data is loading from the network:
If you remember how Controllers are composed from my previous post:
The ListViewController is only responsible for displaying cells of Apps. It is not aware of weither it is downloading data or not. So the activity indicator canno't be added in that controller.
Instead we could add the ActivityIndicator in the AppViewCoordinator, however, there is another way which is to create a new Container Controller called LoadingViewController. This controller will only be responsible for displaying the activity indicator:
//
// LoadingViewController.swift
// AppStoreViewer
//
// Created by Gil Nakache on 07/01/2019.
// Copyright © 2019 Viseo. All rights reserved.
//
import UIKit
public class LoadingViewController: UIViewController {
// MARK: - Variables
private let contentViewController: UIViewController
private let activityIndicator = UIActivityIndicatorView(style: .gray)
// MARK: - Init
init(contentViewController: UIViewController) {
self.contentViewController = contentViewController
super.init(nibName: nil, bundle: nil)
}
public required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Lifecycle
public override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
activityIndicator.hidesWhenStopped = true
add(asChildViewController: contentViewController)
view.addSubview(activityIndicator)
activityIndicator.center(in: view)
}
// MARK: - Public functions
public func startLoading() {
contentViewController.view.isHidden = true
activityIndicator.startAnimating()
}
public func endLoading() {
activityIndicator.stopAnimating()
contentViewController.view.isHidden = false
}
}
The code is very simple. This controller is initialized with another controller which is added as a child View Controller.
When you call the method startLoading, you hide the content a and display the activity indicator and when you call endLoading, you hide the indicator and display the content.
Here is how we use it from the AppViewCoordinator. We start by declaring it as a variable:
private lazy var loadingViewController = LoadingViewController(contentViewController: appsViewController)
The in the viewDidLoad method we replace the add method with the following:
add(asChildViewController: loadingViewController)
Finally, we modify our viewWillAppear code by calling the startLoading and endLoading methods:
public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let ressource = AppStoreRessource()
loadingViewController.startLoading()
ressource.getApps(top: 200, appType: appType) { apps, _ in
//
self.loadingViewController.endLoading()
self.apps = apps
self.appsViewController.list = apps
}
}
Creating a ViewController may seem a little overkill just to add a simple Activity Indicator, however we now have a nice reusable LoadingViewController that can be used anytime you need to add an Activity Indicator to a view.
Here is the new hierarchy of controllers for this application:
All the code above can be found in the following repository: