Friday, July 14, 2017

Swift access modifiers

Swift access modifiers

Swift access modifiers

Open:
open classes and class members can be subclassed and overridden both within and outside the defining module (target). Open access is the highest (least restrictive) access level.

Public:
public classes and class members can only be subclassed and overridden within the defining module (target).

Internal:
Enables an entity to be used within the defining module (target). You typically use internal access when defining an app’s or a framework’s internal structure.

FilePrivate:
Restricts the use of an entity to its defining source file. You typically use fileprivate access to hide the implementation details of a specific piece of functionality when those details are used within an entire file.

Private:
Restricts the use of an entity to its enclosing declaration. You typically use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration. private access is the lowest (most restrictive) access level.

Final:
The final keyword is not an access level but you can add it to any of the access levels (apart from open) to prevent subclassing or overriding.


Now the question is What does it mean by same module?
Let’s understand it by example: many times we subclass UITextField (class), which is a part of UIKIT (Different module) but we can do this because it is defined as open. Same applies for class member and methods.

@available(iOS 2.0, *)
open class UITextField : UIControl, UITextInput, NSCoding, UIContentSizeCategoryAdjusting {
...
...
}

UITextField: Swift access modifiers

Some other observations: (I have checked it with swift 3.0.)

In order to apply the open and public access modifiers we need to inherit our class from NSObject. Or we may get below error while using outside of class.
'openClass' initializer is inaccessible due to 'internal' protection level.
'publicClass' initializer is inaccessible due to 'internal' protection level.
'fileprivateFunc' is inaccessible due to 'fileprivate' protection level

We cannot inherit public class outside the module. We get below error:
Cannot inherit from non-open class 'publicClass' outside of its defining module

We cannot access internal method or object outside the module.
'internalObject' is inaccessible due to 'internal' protection level

In other file or module,We get below error when we try to create object of FilePrivate class and private class respectively.
Use of undeclared type 'fileprivateClass'
Use of undeclared type 'privateClass'

In same file, we can inherit or create object of private class as below and we can access all class members and methods which are not private.

fileprivate var privateClassObject = privateClass()

private class IprivateClass :privateClass {
}

Here is a link of apple document for more details.

Thursday, July 13, 2017

VIPER- Class binding using Protocol

In last post we have seen how to bind all classes together. In this post we would see app flows from view controller to interactor and to view controller.To make it more decoupled we would generate some protocols and implement it in classes.

Step:1 list-ViewController
Architecting iOS Apps with VIPER - App event flow in VIPER
override func viewDidLoad() {
        super.viewDidLoad()
        DispatchQueue.global().async {
            self.eventHandler?.updateView()
        }
    }

Step:2 list-Presenter
Architecting iOS Apps with VIPER - App event flow in VIPER

func updateView() {
        listInteractor?.findListData()
    }

Step:3 list-Interactor
Architecting iOS Apps with VIPER - App event flow in VIPER


func findListData() {
        //Find data
        //output?.foundListData(aList: nil);
        let reader = FileReader()
        if let data = reader.readJsonFile(name: "company") {
            let myArr:NSArray? = ParseData(aObject: data)
            if myArr != nil {
                output?.foundList(aList: myArr);
            }
        }
    }

Step:4 list-Presenter
Architecting iOS Apps with VIPER - App event flow in VIPER

func foundList(aList:NSArray?) {
        let sortedArray:NSArray? = self.SortCompanyList(aList: aList)
        if(sortedArray != nil) {
            userInterface?.reloadList(alist: sortedArray)
        }
        else {
            userInterface?.showNoContenctView()
        }
    }

Protocols:
1) ViewController Interface:
Implemented   by ViewController
Object owned by Presenter
Architecting iOS Apps with VIPER - Protocol binding in VIPER

protocol listViewInterface {
    func showNoContenctView()
    func reloadList(alist:NSArray?)
}
*********************************************************
class ViewController: UIViewController,listViewInterface
 {
  //MARK: listViewInterface methods implementation
    func reloadList(alist:NSArray?) {
        //reload table view
    }
    func showNoContenctView() {
     //Show alert code
    }
 }
*********************************************************
class listPresenter: NSObject {
    var userInterface:listViewInterface?
}

2) Presenter Interface:
Implemented by Presenter
Object owned by ViewController
Architecting iOS Apps with VIPER - Protocol binding in VIPER

protocol listPresenterInterface {
    func updateView();
}
*********************************************************
class listPresenter: NSObject,listPresenterInterface {
    var userInterface:listViewInterface?
    func updateView() {
        //Call for data adjustment and interactor calling
    }
}
*********************************************************
class ViewController: UIViewController,listViewInterface {
   var eventHandler:listPresenterInterface?
   override func viewDidLoad() {
     super.viewDidLoad()
     self.eventHandler?.updateView();
   }

   //MARK: listViewInterface implementation
    func reloadList(alist:NSArray?) {
        //reload table view
    }
    func showNoContenctView(){
        //Show alert code
        }
 }


3) Interactor Input Interface:
Implemented   by interactor
Object owned  by presenter
Architecting iOS Apps with VIPER - Protocol binding in VIPER

protocol listInteractorInput {
    func findListData()
}
*********************************************************
class listInteractor: NSObject,listInteractorInput {
    func findListData() {
        //Find data
    }
*********************************************************
class listPresenter: NSObject,listPresenterInterface {
    var listInteractor:listInteractorInput?
    func updateView() {
     //Code for data adjustment and interactor calling
     listInteractor?.findListData();
    }
}

4) Interactor output Interface:
Implemented   by presenter
Object owned  by interactor
Architecting iOS Apps with VIPER - Protocol binding in VIPER

protocol listInteractorOutput {
    func foundList(aList:NSArray?)
}
*********************************************************
class listPresenter: NSObject,listPresenterInterface,listInteractorOutput {
    var listInteractor:listInteractorInput?
    var userInterface:listViewInterface?
    
    func updateView() {
        listInteractor?.findListData();
    }
    func foundList(aList:NSArray?) {
       userInterface?.reloadList(alist: sortedArray);
    }
}
*********************************************************
class listInteractor: NSObject,listInteractorInput {
    var output:listInteractorOutput?
    func findListData() {
        //Find data
    }
}

Note:Presenter is implementing two protocols.
This is the end of the post. In next post we will see how VIPER is useful for testing and coverage.

Thursday, July 6, 2017

Eat That Frog- Prepare Thoroughly Before You Begin, Do Your Homework

I have read the book ‘Eat That Frog’, Here is a snippet that I could get from the chapters ‘Prepare Thoroughly Before You Begin’ and 'Do Your Homework':

Prepare Thoroughly Before You Begin
You need to get everything completely ready to work in advance. When everything is laid out in order and sequence you feel much more like getting on with the job.

This seems to be a simple and short thing but it the most important thing before we start anything. It could increase significant changes of successful and perfect completion.  This gives yourself more depth, clear picture to you and prepare your mind for any work.  

Do Your Homework 
If you're not getting better, you're getting worse.
Continuous learning is the minimum requirement for success in any field. 
Read in your field for at least one hour every day. Take every course and seminar available on key skills that can help you.
What are the key skills that can help you the most to achieve better and faster results?

Eat that Frog
If you wish to purchase a book from AMAZON click here: http://amzn.to/2pnTEQB

Have a great day ahead!

VIPER: Router and wireframe - Class binding

We will see binding of all classes.Let us bind for list view.

Here is a list of classes with whom we are going to interact.
AppDelegate – Standard UIApplicationMain default class.
AppDependencies – A class which has methods to bind all classes.
Root-wireframe - A class which has all possible kind of transition code. (like push, pop, present etc.) List-wireframe - A class knows how to show its UI and all possible forward flow.

And other all classes that we have seen previous are presenter, interactor, view controller and entity. Here is a step by step process to bind all the classes.

Step:1 class name: AppDelegate We create object of dependency class.
Architecting iOS Apps with VIPER

let appDependencies = AppDependencies()

Step:2 class name: AppDelegate, With dependency class we call its method.
Architecting iOS Apps with VIPER


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        let wireframe = appDependencies.configureDependencies()
        return true
    }

Step:3 class name: AppDependencies  In dependency class we can put all shared instance object and other objects we put it in a method.
Architecting iOS Apps with VIPER

class AppDependencies {
    let rootWireFrame = RootWireframe()
    //this is the root object so we need to create here, others go to their own function
    //return value could be replaced with wireframe object

    func configureDependencies() -> listWireFrame {
        let listWireframe = listWireFrame()

        listWireframe.rootWireframe = rootWireFrame
        return listWireframe
    }
}

Step:4 class name: AppDependencies
Architecting iOS Apps with VIPER

func configureDependencies() -> listWireFrame {
        let listWireframe = listWireFrame()
 let Presenter = listPresenter()

 listWireframe.rootWireframe = rootWireFrame
 listWireframe.listPresenter = Presenter
 return listWireframe
}

Step:5 class name: AppDependencies
Architecting iOS Apps with VIPER

func configureDependencies() -> listWireFrame {
        let listWireframe = listWireFrame()
        let Presenter = listPresenter()
        let Interactor = listInteractor()
        
        listWireframe.listPresenter = Presenter
        Presenter.listInteractor = Interactor
        return listWireframe
    }

Step:6 AppDependencies
Architecting iOS Apps with VIPER

func configureDependencies() -> listWireFrame {
        let listWireframe = listWireFrame()
        let Presenter = listPresenter()
        let Interactor = listInteractor()
        
        listWireframe.listPresenter = Presenter
        Presenter.listInteractor = Interactor
        Interactor.output = Presenter
        listWireframe.rootWireframe = rootWireFrame
        return listWireframe
    }

Step:7 class name: AppDelegate
Architecting iOS Apps with VIPER

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        let wireframe = appDependencies.configureDependencies()
        wireframe.presentListInterfaceFromWindow(window: window!)
        return true
    }

class name: list-wireframe
func presentListInterfaceFromWindow(window: UIWindow) {
        let viewController = listViewControllerFromStoryboard()
        viewController.eventHandler = listPresenter
        listVC = viewController
        listPresenter!.userInterface = viewController
        rootWireframe?.showRootViewController(viewController: viewController, inWindow: window)
    }

Step:8 class name: list-wireframe
Architecting iOS Apps with VIPER

func presentListInterfaceFromWindow(window: UIWindow) {
        let viewController = listViewControllerFromStoryboard()
        viewController.eventHandler = listPresenter
        listVC = viewController
        listPresenter!.userInterface = viewController
        rootWireframe?.showRootViewController(viewController: viewController, inWindow: window)
    }

Here is a full flow of binding of all classes.
Architecting iOS Apps with VIPER



Thursday, June 29, 2017

Eat That Frog- Obey the Law of Forced Efficient

I have read the book ‘Eat That Frog’, Here is a snippet that I could get from the chapter ‘Obey the Law of Forced Efficient’:

There will never be enough time to do everything you have to do, but there is always enough time to do the most important thing.

What are my highest value activities?
You must be crystal clear about your highest value activities before you begin work.

What can I and only I do that, if done well, will make a real difference?
Your job is to be clear about the answer and then to start and work on this task before anything else.

What is the most valuable use of my time right now?
Your most powerful thinking tool for success is your ability to discriminate between one priority and another. Take a few minutes each day and fix this first.


Eat that Frog
    If you wish to purchase a book from AMAZON click here: http://amzn.to/2pnTEQB

    Have a great day ahead!

    Sunday, June 25, 2017

    VIPER: Interactor and Entity

    In this post, we will see interactor work and entity engagement with it. Currently we have not attached it with any kind of data, now we will load up some to data and try to show it in view which is all the way back to presenter.

    Use Case: Now we know about view and presenter, it’s time for Interactor. We want to see name of the person and the company in UIView. For that we have one JSON file which we will load. 

    Task: Implement interactor, implement file reader, read the file, convert data in to model, transform it as per view and show the details.
    Anticipated output:
    VIPER: Interactor and Entity

    Here is a JSON file as of now which we want to load and show the data.
    //JSON file
    [{
      "_id": "58f9a19680685a4e1e6d5016",
      "index": 0,
      "guid": "0b10fe86-a222-4ca5-a094-0082b7d4c1af",
      "isActive": false,
      "balance": "$2,107.15",
      "picture": "http://placehold.it/32x32",
      "age": 35,
      "eyeColor": "green",
      "name": {
       "first": "Bertha",
       "last": "Irwin"
      },
      "company": "COMSTAR",
      "email": "bertha.irwin@comstar.net",
      "phone": "+1 (806) 584-3949",
      "address": "303 Vermont Street, Concho, Arizona, 1707",
      "favoriteFruit": "banana"
     },
     {
      "_id": "58f9a196c020af14f6726d3a",
      "index": 1,
      "guid": "d1695e0f-2d05-465e-8e14-eca9ad64c426",
      "isActive": false,
      "balance": "$1,194.79",
      "picture": "http://placehold.it/32x32",
      "age": 30,
      "eyeColor": "green",
      "name": {
       "first": "Norton",
       "last": "Curtis"
      },
      "company": "RECRISYS",
      "email": "norton.curtis@recrisys.tv",
      "phone": "+1 (850) 571-3013",
      "address": "106 Bliss Terrace, Vandiver, Mississippi, 9292",
      "favoriteFruit": "strawberry"
     },
     {
      "_id": "58f9a196d46f3d10560759bd",
      "index": 2,
      "guid": "bf810ee3-3bc4-44e0-8056-3ac3815d2887",
      "isActive": true,
      "balance": "$2,259.39",
      "picture": "http://placehold.it/32x32",
      "age": 38,
      "eyeColor": "brown",
      "name": {
       "first": "Zamora",
       "last": "Weber"
      },
      "company": "PERMADYNE",
      "email": "zamora.weber@permadyne.co.uk",
      "phone": "+1 (929) 591-2437",
      "address": "787 Crystal Street, Williston, Wisconsin, 6408",
      "favoriteFruit": "strawberry"
     },
     {
      "_id": "58f9a196fe6014ff5fd07cb5",
      "index": 3,
      "guid": "e5cfcd2e-2911-4293-9a0f-3a53374ea1d9",
      "isActive": true,
      "balance": "$3,019.42",
      "picture": "http://placehold.it/32x32",
      "age": 25,
      "eyeColor": "blue",
      "name": {
       "first": "Barnes",
       "last": "Pickett"
      },
      "company": "RECRISYS",
      "email": "barnes.pickett@RECRISYS.info",
      "phone": "+1 (804) 532-3235",
      "address": "500 Milton Street, Nadine, Kansas, 8781",
      "favoriteFruit": "apple"
     },
     {
      "_id": "58f9a196361f66d65c9b39f8",
      "index": 4,
      "guid": "80ca8651-5edf-4d11-bb09-688f654ff3ad",
      "isActive": true,
      "balance": "$3,334.51",
      "picture": "http://placehold.it/32x32",
      "age": 33,
      "eyeColor": "brown",
      "name": {
       "first": "Cohen",
       "last": "James"
      },
      "company": "COMSTAR",
      "email": "cohen.james@comvene.name",
      "phone": "+1 (953) 454-3801",
      "address": "230 Lefferts Avenue, Navarre, Tennessee, 3443",
      "favoriteFruit": "strawberry"
     },
     {
      "_id": "58f9a19607f1cc3aafc21c5b",
      "index": 5,
      "guid": "df311b09-081c-4a31-b30f-a87700728244",
      "isActive": false,
      "balance": "$2,046.56",
      "picture": "http://placehold.it/32x32",
      "age": 32,
      "eyeColor": "green",
      "name": {
       "first": "Vanessa",
       "last": "Sanchez"
      },
      "company": "COMSTAR",
      "email": "vanessa.sanchez@magmina.biz",
      "phone": "+1 (877) 430-2487",
      "address": "665 Norfolk Street, Bawcomville, Kentucky, 8056",
      "favoriteFruit": "banana"
     }
    ]
    

    Now Here is an interactor class:
    class Interactor: NSObject {
        func findListData() {
            //Find data
            let file = FileReader();
            //We can set default argument in parms it self - a Swift feature
           // file.readJsonFile(name:"company", exten: "json")
            if let data = file.readJsonFile(name:"company") {
                let myArr:NSArray? = ParseData(aObject: data);
                if myArr != nil {
                    presenter?.foundList(aList: myArr);
                }
            }
        }
        //MARK: Model parse
        func ParseData(aObject:Any) -> NSArray? {
            let myArr : NSMutableArray = NSMutableArray();
            if aObject is NSArray {
                for  mydata in aObject as! NSArray {
                    let data = mydata as! NSDictionary
                    let mymodel : CompanyModel  = CompanyModel.init(fname: data.value(forKeyPath:"name.first") as! String, lname: data.value(forKeyPath:"name.last") as! String, company: data.value(forKey:"company") as! String)
                    myArr.add(mymodel);
                }
                return myArr;
            }
            return nil;
        }
        
    }
    

    Here is a file reader class:
    class FileReader:NSObject {
        func readJsonFile(name:String, exten:String="json") -> Any? {
            do {
                if let file = Bundle.main.url(forResource:name, withExtension:exten) {
                    let data = try Data(contentsOf: file)
                    let json = try JSONSerialization.jsonObject(with: data, options: [])
                    if let object = json as? [String: Any] {
                        // json is a dictionary
                        // print(object)
                    } else if let object = json as? [Any] {
                        // json is an array
                        // print(object)
                        return object;
                    } else {
                        print("JSON is invalid")
                    }
                } else {
                    print("no file")
                }
            } catch {
                print(error.localizedDescription)
            }
            return nil;
        }
    }
    

    To transform data in to model we have one company-model class:
    class CompanyModel : NSObject {
        var fName : String = ""
        var lName : String = ""
        var company : String = ""
        init(fname:String,lname:String,company:String) {
            self.fName = fname
            self.lName = lname
            self.company = company
        }
    }
    

    There are some changes which we have to do in order to show the data. In presenter class, we will replace “foundList” method with below code:
    func foundList(aList:NSArray?) {
            if(aList != nil) {
                userInterface?.reloadList(alist: aList)
            }
            else {
                userInterface?.showNoContenctView()
            }
        }
    

    Now we want to show name, in view It is divided in two partition First name and Last name.We will add one method which can return these two in a single entity. To do so we will add one function in a model class.
    var name : String { get {
            return "\(fName) \(lName)"
            }
        }
    


    Now here is a code for UIView:
    extension  ViewController: UITableViewDataSource,UITableViewDelegate {
        //MARK:- TableView methods
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return myArr!.count
        }
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: ListEntryCellIdentifier, for: indexPath as IndexPath) as! listCell
            let myData:CompanyModel = myArr!.object(at: indexPath.row) as! CompanyModel
            cell.title.text = String(myData.name)
            cell.companyName.text = String(myData.company)
            cell.selectionStyle = UITableViewCellSelectionStyle.none
            return cell
        }
        //MARK: ViewInterface implementation
        func reloadList(alist:NSArray?) {
            myArr = alist
            if myArr != nil {
                DispatchQueue.main.async {
                    self.listTableView?.reloadData();
                }
            }
        }
        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)
        }
    }
    
    

    At this point of time there is no major code in presenter, now we will change the requirement and see how presenter could be used.

    Time for twist: We want to sort the data and show the list as per their company and want to show the balance.

    Anticipated output:


    VIPER: Interactor and Entity

    To do so we need to alter data in model, presenter and UIView:
    class model code change:
     init(fname:String,lname:String,company:String,balance:String) {
            self.fName = fname
            self.lName = lname
            self.company = company
            self.balance = balance
        }
    

    Here is a change in code of presenter:
     func foundList(aList:NSArray?) {
            let sortedArray:NSArray? = self.SortCompanyList(aList: aList)
            if(sortedArray != nil) {
                userInterface?.reloadList(alist: sortedArray);
            } else {
                userInterface?.showNoContenctView()
            }
        }
    //This function is used to sort the data as we require.
        func SortCompanyList(aList:NSArray?) -> NSArray? {
            let sortedArray: NSMutableArray = []
            if(aList != nil) {
                let listOfCompany:NSArray? = aList?.value(forKeyPath:"@distinctUnionOfObjects.company") as? NSArray
                if(listOfCompany != nil) {
                    for companyName in listOfCompany! {
                        let predicate = NSPredicate(format: "%K = %@", "company", companyName as! NSObject)
                        let filteredContacts = aList?.filtered(using: predicate)
                        if ((filteredContacts?.count)! > 0) {
                            let sortedDict = NSDictionary.init(object: filteredContacts!, forKey:companyName as! NSCopying)
                            sortedArray.add(sortedDict)
                        }
                    }
                }
                
            }
            return (sortedArray.count > 0) ? sortedArray : nil 
        }
    

    Now here is a code for UIView:
    extension  ViewController: UITableViewDataSource,UITableViewDelegate{
        //MARK:- TableView methods
         func numberOfSections(in tableView: UITableView) -> Int {
            return myArr!.count
        }
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
             let dictSection:NSDictionary = (myArr?.object(at:section) as! NSDictionary)
            return (dictSection.object(forKey:dictSection.allKeys.first!) as! NSArray).count
        }
        func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
            let dictSection:NSDictionary = (myArr?.object(at:section) as! NSDictionary)
            let title:String = " \(dictSection.allKeys.first as! String)"
            return title
        }
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: cListEntryCellIdentifier, for: indexPath as IndexPath) as! listCell
            //Fetch model
            let dictSection:NSDictionary = (myArr?.object(at: indexPath.section) as! NSDictionary)
            let myData:CompanyModel = (dictSection.object(forKey:dictSection.allKeys.first!) as! NSArray).object(at: indexPath.row) as! CompanyModel
            //Set model data
            cell.title.text = String(myData.name)
            cell.companyName.text = String(myData.balance)       
            cell.selectionStyle = UITableViewCellSelectionStyle.none
            return cell
        }
        //MARK: ViewInterface implementation
        func reloadList(alist:NSArray?) {
            myArr = alist;
            if myArr != nil {
                DispatchQueue.main.async {
                    self.listTableView?.reloadData();
                }
            }
        }
        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)
        }
        
    }
    
    

    This is the end of second VIPER post, In next post we will explore router/wireframe code and  unit test case for the same app.

    Tuesday, June 20, 2017

    5 Levels of Leadership

    Find out more with this summary of John Maxwell's The 5 Levels of Leadership.

    Level 1: Position (This would mostly comes with job title, People follow because they have to.)

    Level 2: Permission (People follow because they want to. as you personally taking interest in every member, Why, What and How they work? and set them on level 1 by being their mentor.)

    Level 3: Production (People follow because of what you have done for the organization. You encourage Level 2 people to do and be with them.)

    Level 4: People Development (People follow because of what you have done for them. At this stage people at Level 3 should not need your strict mentorship, they can do it and can do it very well.)

    Level 5: The Pinnacle (People follow because of who you are and what you represent. At this stage people do it and Level 4 would watch them.)


    5 Levels of Leadership

    Leadership is an Action and its always on going, learning and growing process.
    View a quick talk on leadership

    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.

    Tuesday, June 13, 2017

    Eat That Frog- Focus On Key Result Areas

    I have read the book ‘Eat That Frog’, Here is a snippet that I could get from the sixth chapter ‘Focus On Key Result Areas’:


    • Identify the key result areas of your work. 
    • ASK: What one skill, if I developed and did it in an excellent fashion, would have the greatest positive impact on my career?" Because, your weakest key result area sets the height at which you can use all your other skills and abilities. Your poor performance in the one key area can hold you back. 
    • The better you become in a particular skill area, the more motivated you will be to perform that function, the less you will procrastinate.


    Eat that Frog
    If you wish to purchase a book from AMAZON click here: http://amzn.to/2pnTEQB

    Have a great day ahead!

    Saturday, June 3, 2017

    Eat That Frog-Plan Every Day in Advance

    I have read the book ‘Eat That Frog’, Here is a snippet that I could get from the second chapter ‘Plan Every Day in Advance ’:

    • How do you eat an elephant? The answer, of course, is “One bite at a time!”  
    • You break it down into specific step-by-step activities and then you start on the first one. 
    • Begin today to plan every day, week, and month in advance. 
      • Make your list the night before. 
      • A monthly list that you make up at the end of the month for the month ahead.
      • A weekly list where you plan your entire week in advance. 
      • Always work from a list. When something new comes up, add it to the list before you do it.  
    Eat that Frog
    If you wish to purchase a book from AMAZON click here: http://amzn.to/2pnTEQB

    Have a great day ahead!

    Eat That Frog - Practice the ABCDE Method Continually

    I have read the book ‘Eat That Frog’, Here is a snippet that I could get from the fifth chapter ‘Practice the ABCDE Method Continually’:


    The ABCDE Method is a powerful priority-setting technique that you can use every single day. A tadpole should never distract you, when a big frog is sitting there waiting to be eaten. 


    1. "A" item is defined as something that is very important. If you have more than one "A" task, you prioritize these tasks by writing A-1, A- 2, A-3, and so on.
    2. "B" item is defined as a task that you should do. But it has only mild consequences.

    3. "C" task is defined as something that would be nice to do.
    4. "D" task is defined as something you can delegate to someone else.
    5. "E" task is defined as something that you can eliminate altogether. It is something you continue to do out of habit or because you enjoy it.

    Eat that Frog
    If you wish to purchase a book from AMAZON click here: http://amzn.to/2pnTEQB

    Have a great day ahead!

    Friday, May 26, 2017

    Eat That Frog - Consider the Consequences

    I have read the book ‘Eat That Frog’, Here is a snippet that I could get from the fourth chapter ‘Consider the Consequences ’:



    1. Long-time perspective turns out to be more important than any other single factor in determining your success in life and at work.

    2. Always ask yourself, "What are the potential consequences of doing or not doing this task?"

    3. Failures do what is tension relieving, while winners do what is goal achieving.

    4. For example, coming into work earlier, reading regularly in your field, taking courses to improve your skills, and focusing on high-value tasks in your work will all combine to have an enormous positive impact on your future.
    On the other hand, coming into work at the last moment, reading the newspaper, drinking coffee, and socializing with your coworkers may seem fun and enjoyable in the short term.



    Eat that Frog
    If you wish to purchase a book from AMAZON click here: http://amzn.to/2pnTEQB

    Have a great day ahead!

    Tuesday, May 23, 2017

    Eat That Frog - Apply the 80/20 Rules to Everything

    I have read the book ‘Eat That Frog’, Here is a snippet that I could get from the third chapter ‘Apply the 80/20 Rules to Everything ’:

    1.20 percent of your activities will account for 80 percent of your results.

    2.One item on a list of ten tasks that you have to do can be worth more than all the other nine items put together. This task is invariably the frog that you should eat first.

    3.Always ask yourself, "Is this task in the top 20 percent of my activities or in the bottom 80 percent?”

    4.Resist the temptation to clear up small things first. The task comes under 20 percent could be easy or hard. The fact is that the amount of time required to complete an important job is often the same as the time required to do an unimportant job.


    Eat that Frog
    If you wish to purchase a book from AMAZON click here: http://amzn.to/2pnTEQB

    Have a great day ahead!

    Thursday, May 11, 2017

    Eat That Frog - Think on paper

    I have read the book ‘Eat That Frog’, Here is a snippet that I could get from the first chapter ‘Think on paper’:

    Clarity is the most important concept. 
    • Decide exactly what you want Write it down. 
    • Set a deadline on your goal. 
    • Make a list of everything that you can think of that you are going to have to do to achieve your goal. 
    • Organize the list into a plan. 
    • Take action on your plan immediately. 
    • Resolve to do something every single day that moves you toward your major goal. 
    • Think about your goals and review them daily.
    Eat that Frog

    If you wish to purchase a book from AMAZON click here: http://amzn.to/2pnTEQB

    Have a great day ahead!