Swift Programming : Modular is Better
Meet the single responsibility principle by modularizing the code base.
We often develop an apps in short time but very complex. To meet the delivery target, it would be better to using some pod dependencies. SJProgressHUD is once of modular dependencies for displaying popup or loading process which available on Cocoapods. The alternates are SVProgressHUD, MBProgressHUD, JQProgressHUD.
Let choose SJProgressHUD for example. We can attach SJProgressHUD.show() every where such as UIViewController classes, AppDelegate class, Presenter or Controller (if you are using MVP/MVC) or maybe inside Model classes. It is work fine, but we are violate the software development principle : don't repeat yourself. If we put it on model, the other issue is single responsibility violation. The model should not responsible to show a progress view. If we fail to define boundary between model class and view class, we will get serious problem on the next because of tightly coupled among parts.

Your spaghetti Code must be refactored.
There are many solutions to refactor it. First, we make an extension class from UIViewController. In the extension files, add some functions which will be used to handling loading view such as showLoading(), showError(), and showSuccess().
import SJProgressHUDclass UIViewControllerExtension {
extension UIViewController {
func showWaiting(message: String){
SJProgressHUD.showWaiting(message)
}
func showError(message: String){
SJProgressHUD.showError(message)
}
}
}
After create an extension, we are allowed to call showWating(“getting doctors, please wait...”) from anywhere as long as on UIViewController. Let see the problem, actually not all derivatives of UIViewController need to know about that. For example we have AboutVC which only show the applications version.
//no need to import SJProgressHUD
class AboutVC:UIViewController{
func viewDidLoad(){ }
func viewWillAppear(){
//magic here... wa can call it any where on each UIViewController.
//but unfortunetly the AboutVC no need to know about it.
showWaiting("please wait...")
}
}
Modularizing the code base.
The second solution is making a new component which responsible to control the SJProgressViewHUD, let say UILoadingView. It should be easy to plug and remove from UIViewController. Keep it meet the Single Responsibility principle, so if somehow we need to replace the SJProgressViewHUD with SVProgressViewHUD just only make changes on UILoadingView part.
protocol UILoadingView {
func showLoading()
func showLoadingWithLabel(title:String?, subtitle:String)
func showErrorWithLabel(message: String)
func showSuccessWithLabel(message:String)
func hideLoading()
}Let make the UILoadingView just only attachable into UIViewController by using where Self: UIViewController. In this part we also make the default implementation. Next time we only refactor this when need make a changes with SJProgressViewHUD.
import SJProgressViewHUD
extension UILoadingView where Self: UIViewController {
func hideLoading(){
HUD.hide()
}
func showLoading(){
HUD.show(.progress)
}
func showLoadingWithLabel(title:String? = "Waiting", subtitle:String){
HUD.show(.labeledProgress(title: title, subtitle: subtitle))
}
func showErrorWithLabel(message: String){
HUD.flash(.labeledError(title: "Failure", subtitle: message), delay: 1.5)
}
func showSuccessWithLabel(message:String){
HUD.flash(.labeledError(title: "Success", subtitle: message), delay: 1.5)
}
}By attaching the UILoadingView into UIViewController, now we can call showLoading(“please wait…”) from this class. Otherwise we are no need to attach the UILoadingView if the UIViewController is didn’t have any requirement to show progress view.
class LoginVC: UIViewController, UILoadingView{
func anyProcessNeedToShowLoadingView(){
showLoadingWithLabel(subtitle: "please wait...")
}
}Thats it. Last but not least, before your code really complicated it will be better if we consider about modular code base.
Thanks for reading :)

