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