Wednesday, June 14, 2017

VIPER an iOS architecture

I have been practicing VIPER architecture since one year and I found lots of ups and down while using it.
In this blog I will try to explain and simplify VIPER architecture.
Here are the two images which you could see when you search for VIPER architecture. 

VIPER an iOS architecture


VIPER an iOS architecture


Both are almost same and right. It is on you and use cases that which one you could choose to use. We will use both images at various time as we proceed.

Why VIPER?
Most of the iOS Apps follows MVC pattern and since much of the application code cannot fit in model or view are ended up in ViewController which makes our ViewController the Massive View Controller. VIPER could focus to reduce the load of ViewController.
Testing was never a major part of making iOS Apps and it is too difficult to test with various architectures but VIPER helps a lot in this area too.
We can divide code on basis of functionality like login, register, view account etc.

What is VIPER?
Here what VIPER stands for:
V-> View
I-> Interactor
P-> presenter
E-> Entity
R-> Router
Here is a general diagram which helps you to understand the flow.

VIPER Flow Diagram



View: One super secret is Your View = ViewController class + Interface View. It is a passive and can request presenter to update itself. The presenter does not know about any existence of UI elements like UIButton or UILabel, but it maintains the content. Till now what you do in ViewController class is your View and we will practice to reduce its load so now on View Controller has to worry only about showing content. And other responsibilities we will pass to presenter, interactor and so on.

Presenter: It consist the logic to drive the UI. And also handles the events passed by View and interactor. Lets explore this both using example.


Use case: We have a ViewController and we want to show some content in the view, however this is our first step we do not have any content to show, so we would show only popup with no content.

Prior code:
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
            self.updateView()
    }
    func updateView() {
         var myArray:NSArray? = nil ;
        //now we would call web service or db method to load data so that myArray != nil
        if(myArray != nil) {
            //Do change to make it appropriate with regards to view, like change array into model - entity form.
        }
        else {
            let alert = UIAlertController.init(title: "VIPER", message: "No content to show", preferredStyle:.alert)
            let okAction = UIAlertAction.init(title: "OK", style: UIAlertActionStyle.default, handler: nil)
            alert.addAction(okAction)
            self.present(alert, animated:true, completion: nil)
        }
    }

}

After adding presenter:

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
            presenter.updateView()
    }
    func showNoContenctView(){
        let alert = UIAlertController.init(title: "VIPER", message: "No content to show", preferredStyle:.alert)
        let okAction = UIAlertAction.init(title: "OK", style: UIAlertActionStyle.default, handler: nil)
        alert.addAction(okAction)
        self.present(alert, animated:true, completion: nil)
    }

}
class Presenter:NSObject {
    func updateView() {
        //ask interactor for data.
        interactor.findListData()
      }
   
    //This method will be called by interactor once interactor gets the data
    func foundList(aList:NSArray?) {
        if(aList != nil) {
            //if list != nil //we would be doing some data formation before passing this to the view.
        }
        else {
            userInterface?.showNoContenctView();
        }
    }
    
}

Draft:1 This is the end of first draft, in next post we will learn about interactor and entity.

No comments:

Post a Comment

Please do not spam.