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.