top

Search

Swift Tutorial

ARC Overview Optional Chaining Type Casting Extensions Protocols Generics Access Control ARC Overview In order to monitor and handle the memory usage of your app, Swift utilizes Automatic Reference Counting (ARC). As a programmer, you are not required to think about memory management as it is being taken care of by ARC. If such instances are no longer required, ARC automatically releases the memory used by class instances. In a few instances, however, ARC needs further data on the connections between components of your code to handle your memory. ARC allocates a piece of memory for storing data every time you generate a fresh class instance . This memory contains data on the type of class and any stored characteristics connected with that instance. ARC assures an additional property of class instances which  no longer take up memory space when they are not required, and hence the space can be utilized for some other purposes. However, In case if ARC deallocates an instance that was already being used, the instance's properties would no longer be accessed. Infact , if  the user attempted to achieve the above kind of instance, the app would most probably crash. ARC monitors the number of properties , constants and variables presently referred to each class instance , to ensure that instances do not vanish as required. As long as at least one active reference exists still, ARC will not deallocate an instance.To enable this, property, constant or variable refers strongly to instance where the user assigns a class instance to a property, constant or variable. The reference is called a "strong" reference . It is being referred as strong here since the  instance does not allow it to be distributed for as long as it remains a same i:s“Strong reference”.Example class Person {     let name: String     init(name: String) {         self.name = name         print("\(name) is being initialized")     }     deinit {         print("\(name) is being deinitialized")     }  }  ARC Strong Reference Cycles Class Instances  class studmarks {  let name:String  var stud: student?     init (name:String){  print("Initializing: \(name)")  self.name = name  }     deinit {  print("Deallocating: \(self.name)")  }  }  class student {  let name:String  var strname: studmarks?     init (name:String){  print("Initializing: \(name)")  self.name = name  }     deinit {  print("Deallocating: \(self.name)")  }  }  var shiba: studmarks?  var mari: student?  shiba = studmarks(name:"Hello")  mari = student(name:"ARC")  shiba!.stud = anushka  mari!.strname = SwatiARC Weak and Unowned References These references are used to allow an individual instance in a reference process to refer to other instances. Instead of taking great care of the strong reference cycle, the instance may refer to every single instance. If the user understands that a certain instance can return nil, we can point out that the weak reference is used. If something is returned instead of nil, then declare it with an unknown reference. Weak Reference classmodule{ let name:String    init(name:String){self.name = name } varsub: submodule?    deinit {print("\(name) Is The Main Module")} } class submodule { let number:Int    init(number:Int){self.number = number }    weak var topic:module?    deinit {print("Sub Module with its topic number is \(number)")} } var toc:module? var list: submodule? toc =module(name:"ARC") list = submodule(number:4) toc!.sub= list list!.topic = toc toc =nil list =nil The output of the above program would be ARC Is The Main Module Sub Module with its topic number is 4Unowned References class student {    let name: String    var section: marks?    init(name: String) {       self.name = name    }    deinit { print("\(name)") } } class marks {    let marks: Int    unowned let stname: student    init(marks: Int, stname: student) {       self.marks = marks       self.stname = stname    }    deinit { print("Marks Obtained by the student is \(marks)") } } var module: student? module = student(name: "ARC") module!.section = marks(marks: 98, stname: module!) module = nil The output of the above program would be ARC  Marks Obtained by the student is 98Strong Reference Cycles for Closures When we actually assign a closure statement to the class instance property and to the body of the closure to capture a particular instance ,there is a scope that the strong reference cycle can occur. Strong reference to the closure in particular is well addressed and defined as  by 'self.someProperty' or 'self.someMethod()'. Strong reference cycles are in turn used as reference types for the closures. The strong reference cycle can happen if a closure for the class instance property and the body of the closure is assigned in order to capture a specific instance. self.someProperty' or' self.someMethod()' is the strong reference to closure. As reference types for closures, strong reference cycles are used. class HTMLElement{     let samplename:String     let text:String?     lazy var asHTML:()->String={        if let text = self.text {           return "<\(self.samplename)>\(text)</\(self.samplename)>"  } else {           return "<\(self.samplename) />"  }  }     init(samplename:String, text:String?= nil){        self.samplename = samplename        self.text = text  }     deinit {        print("\(samplename) is being deinitialized")  }  }  var paragraph:HTMLElement?=HTMLElement(samplename:"p", text:"Welcome to Closure SRC")  print(paragraph!.asHTML())  The output for the above program would be   <p>Welcome to Closure SRC</p> Optional Chaining Optional chaining is an operation on an optional that could presently be nil for querying and calling properties, methods, and subscriptions. If the options include the value, the property, methods, or subscript call is successful, if the optional is nil, then nil returns the property, method or subscript call. Many queries can be linked together, and if any link is nil, the whole chain will fail gracefully. Optional Chaining as an Alternative to Forced Unwrapping If you want to call a property, method or subscript on optional value if you have an optional non-nil, you indicate optional chaining by putting the question mark(?). This is very comparable to a mark(!) after an optional value to force its value to be unwrapped. The major distinction is that if the optional is nil, optional chaining fails, whereas forced unwrapping causes a runtime error when the optional is nil. Program for optional chaining by (!) classLoksabhaPoll{  var candidate:Constituency? //Optional  }  lass Constituency{  var name ="Hajipur"  }  let cand =LoksabhaPoll ()  let candname = cand.candidate!.name //forced unwrapping  The output for the above program would be as follows  fatal error: unexpectedly found nil while unwrapping an Optional value  0 Swift 4 0x0000000103410b68  llvm::sys::PrintStackTrace(__sFILE*) + 40  1 Swift 4 0x0000000103411054 SignalHandler(int) + 452  2 libsystem_platform.dylib 0x00007fff9176af1a _sigtramp + 26  3 libsystem_platform.dylib 0x000000000000000b _sigtramp + 1854492939  4 libsystem_platform.dylib 0x00000001074a0214 _sigtramp + 1976783636  5 Swift 4 0x0000000102a85c39  llvm::JIT::runFunction(llvm::Function*, std::__1::vector > const&) + 329  6 Swift 4 0x0000000102d320b3  llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,  std::__1::vector<std::__1::basic_string, std::__1::allocator >,  std::__1::allocator<std::__1::basic_string, std::__1::allocator > > > const&,  char const* const*) + 1523  7 Swift 4 0x000000010296e6ba Swift 4::RunImmediately(Swift  4::CompilerInstance&, std::__1::vector<std::__1::basic_string,  std::__1::allocator >, std::__1::allocator<std::__1::basic_string,  std::__1::allocator > > > const&, Swift 4::IRGenOptions&, Swift 4::SILOptions  const&) + 1066  8 Swift 4 0x000000010275764b frontend_main(llvm::ArrayRef,  char const*, void*) + 5275  9 Swift 4 0x0000000102754a6d main + 1677  10 libdyld.dylib 0x00007fff8bb9e5c9 start + 1  11 libdyld.dylib 0x000000000000000c start + 1950751300  Stack dump: 0.Program arguments:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/  usr/bin/Swift 4 -frontend -interpret - -target x86_64-apple-darwin14.0.0 -  target-cpu core2 -sdk  /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/  SDKs/MacOSX10.10.sdk -module-name main  /bin/sh: line 47: 15672 Done cat <<'SWIFT 4'  import Foundation  </std::__1::basic_string</std::__1::basic_string</std::__1::basic_string</std::  __1::basic_string Since the values are not stated in their base class, the value ' NIL' is saved and the force unwrapping operation returns a fatal error. Program for optional chaining by (?)  classLoksabhaPoll{  var candidate:Constituency? //Optional  }  lass Constituency{  var name ="Hajipur"  }  let cand =LoksabhaPoll()  if let candname = cand.candidate?.name {     print("Candidate name is \(candname)")  } else {     print("Candidate name cannot be retrieved")  } The output for the above program would be  Candidate name cannot be retrieved  Defining Model Classes for Optional Chaining & Accessing Properties Swift also offers the optional chaining idea in the form of declaring more than one subclass as a model class. This idea is very helpful for defining and accessing complicated models and sub-properties of properties, methods, and subscriptions. class rectangle {     var print: circle?  }  class circle {     var area =[radius]()     var cprint:Int{        return area.count  }     subscript(i:Int)-> radius {        get {           return area[i]  }        set {           area[i]= newValue  }  }     func circleprint(){        print("The number of rooms is \(cprint)")  }     var rectarea: circumference?  }  class radius {     let radiusname:String     init(radiusname:String){ self.radiusname = radiusname }  }  class circumference {     var circumName:String?     var circumNumber:String?     var street:String?     func buildingIdentifier()->String?{        if circumName != nil {           return circumName  } else if circumNumber != nil {           return circumNumber  } else {           return nil  }  }  }  let rectname = rectangle()  if let rectarea = rectname.print?.cprint {     print("Area of rectangle is \(rectarea)")  } else {     print("Rectangle Area is not specified")  } The output for the above program would be   Rectangle Area is not specifiedCalling Methods Through Optional Chaining class rectangle {  varprint: circle?  }  class circle {  var area = [radius]()  var cprint: Int {  return area.count     }     subscript(i: Int) -> radius {  get {  return area[i]        }  set {           area[i] = newValue        }     }     func circleprint() {  print("Area of Circle is: \(cprint)")     }  var rectarea: circumference?  }  class radius {  let radiusname: String     init(radiusname: String) { self.radiusname = radiusname }  }  class circumference {  var circumName: String?  var circumNumber: String?  var circumarea: String?     func buildingIdentifier() -> String? {  if circumName != nil {  return circumName        } elseif circumNumber != nil {  return circumNumber        } else {  returnnil        }     }  }  let circname = rectangle()  if circname.print?.circleprint() != nil {  print("Area of circle is specified)")  } else {  print("Area of circle is not specified")  }  .In the circle () subclass, the function circleprint() is called when an instance 'circname' is created. If the function includes some value, the value is given back, it checks the value by checking 'circname.print?.circleprint() != nil’  to return some specified print message in case of nil.Accessing Subscripts through Optional Chaining To set and retrieve a subscript value we can leverage optional chaining for ensuring whether a call to that subscript returns a value or not.The optional value of a specific subscript can be accessed by  putting before’?’ the subscript braces.Example 1 class rectangle {     var print: circle?  }  class circle {     var area =[radius]()     var cprint:Int{        return area.count  }     subscript(i:Int)-> radius {        get {           return area[i]  }        set {           area[i]= newValue  }  }     func circleprint(){        print("The number of rooms is \(cprint)")  }     var rectarea: circumference?  }  class radius {     let radiusname:String     init(radiusname:String){ self.radiusname =  radiusname }  }  class circumference {     var circumName:String?     var circumNumber:String?     var circumarea:String?     func buildingIdentifier()->String?{        if circumName != nil {           return circumName  } else if circumNumber != nil {           return circumNumber  } else {           return nil  }  }  }  let circname = rectangle()  if let radiusName = circname.print?[0].radiusname {     print("The first room name is \(radiusName).")  } else {     print("Radius is not specified.")  }   The output of the above program would beRadius is not specified. In the example above the membership function, 'radiusName' instance values are not specified.  Example 2 In the below example membership function instance values are specified. class rectangle {  varprint: circle?  }  class circle {  var area = [radius]()  var cprint: Int {  return area.count     }     subscript(i: Int) -> radius {  get {  return area[i]        }  set {           area[i] = newValue        }     }     func circleprint() {  print("The number of rooms is \(cprint)")     }  var rectarea: circumference?  }  class radius {  let radiusname: String     init(radiusname: String) { self.radiusname = radiusname }  }  class circumference {  var circumName: String?  var circumNumber: String?  var circumarea: String?     func buildingIdentifier() -> String? {  if circumName != nil {  return circumName        } elseif circumNumber != nil {  return circumNumber        } else {  returnnil        }     }  }  let circname = rectangle()  circname.print?[0] = radius(radiusname: "Diameter")  let printing = circle()  printing.area.append(radius(radiusname: "Units"))  printing.area.append(radius(radiusname: "Meter"))  circname.print = printing  iflet radiusName = circname.print?[0].radiusname {  print("Radius is measured in \(radiusName).")  } else {  print("Radius is not specified.")  }Accessing Subscripts of Optional Type class rectangle { varprint: circle?  }  class circle {  var area = [radius]()  var cprint: Int {  return area.count     }     subscript(i: Int) -> radius {  get {  return area[i]        }  set {           area[i] = newValue        }     }     func circleprint() {  print("The number of rooms is \(cprint)")     }  var rectarea: circumference?  }  class radius {  let radiusname: String     init(radiusname: String) { self.radiusname = radiusname }  }  class circumference {  var circumName: String?  var circumNumber: String?  var circumarea: String?     func buildingIdentifier() -> String? {  if circumName != nil {  return circumName        } elseif circumNumber != nil {  return circumNumber        } else {  returnnil        }     }  }  let circname = rectangle()  circname.print?[0] = radius(radiusname: "Diameter")  let printing = circle()  printing.area.append(radius(radiusname: "Units"))  printing.area.append(radius(radiusname: "Meter"))  circname.print = printing  var area = ["Radius": [35, 45, 78, 101], "Circle": [90, 45, 56]]  area["Radius"]?[1] = 78  area["Circle"]?[1]--  print(area["Radius"]?[0])  print(area["Radius"]?[1])  print(area["Radius"]?[2])  print(area["Radius"]?[3])  print(area["Circle"]?[0])  print(area["Circle"]?[1])  print(area["Circle"]?[2]) The output for the above program would be   Optional(35)  Optional(78)  Optional(78)  Optional(101)  Optional(90)  Optional(44)  Optional(56)Linking Multiple Levels of Chaining The optional chaining also facilitates multiple subclasses linking with its superclass properties, methods, and subscripts. class rectangle {  varprint: circle?  }  class circle {  var area = [radius]()  var cprint: Int {  return area.count     }     subscript(i: Int) -> radius {  get {  return area[i]        }  set {           area[i] = newValue        }     }     func circleprint() {  print("The number of rooms is \(cprint)")     }  var rectarea: circumference?  }  class radius {  let radiusname: String     init(radiusname: String) { self.radiusname = radiusname }  }  class circumference {  var circumName: String?  var circumNumber: String?  var circumarea: String?     func buildingIdentifier() -> String? {  if circumName != nil {  return circumName        } elseif circumNumber != nil {  return circumNumber        } else {  returnnil        }     }  }  let circname = rectangle()  iflet radiusName = circname.print?[0].radiusname {  print("The first room name is \(radiusName).")  } else {  print("Radius is not specified.")  } The instance values for the' radiusName' member function are not specified in the above program.It will return only else part of function, while returning values we need to define values for membership function. If the value we are trying to retrieve is optional, then optional chaining will also retrieve the optional value.  class rectangle {  varprint: circle?  }  class circle {  var area = [radius]()  var cprint: Int {  return area.count     }     subscript(i: Int) -> radius {  get {  return area[i]        }  set {           area[i] = newValue        }     }     func circleprint() {  print("The number of rooms is \(cprint)")     }  var rectarea: circumference?  }  class radius {  let radiusname: String     init(radiusname: String) { self.radiusname = radiusname }  }  class circumference {  var circumName: String?  var circumNumber: String?  var circumarea: String?     func buildingIdentifier() -> String? {  if circumName != nil {  return circumName        } elseif circumNumber != nil {  return circumNumber        } else {  returnnil        }     }  }  let circname = rectangle()  circname.print?[0] = radius(radiusname: "Diameter")  let printing = circle()  printing.area.append(radius(radiusname: "Units"))  printing.area.append(radius(radiusname: "Meter"))  circname.print = printing  iflet radiusName = circname.print?[0].radiusname {  print("Radius is measured in \(radiusName).")  } else {  print("Radius is not specified.")  } When we run the above program the output would be  Radius is measured in Units.Chaining on Methods with Optional Return Values The subclasses methods can be also accessed by optional chaining. class rectangle {  varprint: circle?  }  class circle {  var area = [radius]()  var cprint: Int {  return area.count     }     subscript(i: Int) -> radius {  get {  return area[i]        }  set {           area[i] = newValue        }     }     func circleprint() {  print("Area of Circle is: \(cprint)")     }  var rectarea: circumference?  }  class radius {  let radiusname: String     init(radiusname: String) { self.radiusname = radiusname }  }  class circumference {  var circumName: String?  var circumNumber: String?  var circumarea: String?     func buildingIdentifier() -> String? {  if circumName != nil {  return circumName        } elseif circumNumber != nil {  return circumNumber        } else {  returnnil        }     }  }  let circname = rectangle()  if circname.print?.circleprint() != nil {  print("Area of circle is specified)")  } else {  print("Area of circle is not specified")  } Type Casting Typecasting is a way of examining the type of instance or treating it as a superclass or subclass different from that of another one in its class hierarchy. The casting of type in Swift is carried out with operators ”is” and “as”. Both operators provide an easy and expressive way of checking a value type or casting a value to a different type.Defining a Class Hierarchy Typecasting is used to check the type of instance to see if it belongs to a specific type of class. It also examines the class hierarchy and its subclasses in order to check and cast these instances in the same hierarchy. classSubjects {  var physics: String     init(physics: String) {  self.physics = physics     }  }  classChemistry: Subjects {  var equations: String     init(physics: String, equations: String) {  self.equations = equations  super.init(physics: physics)     }  }  classMaths: Subjects {  var formulae: String     init(physics: String, formulae: String) {  self.formulae = formulae  super.init(physics: physics)     }  }  let sa = [ Chemistry(physics: "solid physics", equations: "Hertz"),  Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")]  let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")  print("Instance physics is: \(samplechem.physics)")  print("Instance equation is: \(samplechem.equations)")  let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")  print("Instance physics is: \(samplemaths.physics)")  print("Instance formulae is: \(samplemaths.formulae)") The output for the above program would be  Instance physics is: solid physics  Instance equation is: Hertz  Instance physics is: Fluid Dynamics  Instance formulae is: Giga Hertz Type Checking The' is' operator will perform the type check. The' Is' type checks if the instance is a subclass-type instance and returns true if it belongs to this instance, otherwise it returns false. class Subjects {  var physics: String     init(physics: String) {  self.physics = physics     }  }  classChemistry: Subjects {  var equations: String     init(physics: String, equations: String) {  self.equations = equations  super.init(physics: physics)     }  }  classMaths: Subjects {  var formulae: String     init(physics: String, formulae: String) {  self.formulae = formulae  super.init(physics: physics)     }  }  let sa = [  Chemistry(physics: "solid physics", equations: "Hertz"),  Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),  Chemistry(physics: "Thermo physics", equations: "Decibels"),  Maths(physics: "Astro Physics", formulae: "MegaHertz"),  Maths(physics: "Differential Equations", formulae: "Cosine Series")]  let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")  print("Instance physics is: \(samplechem.physics)")  print("Instance equation is: \(samplechem.equations)")  let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")  print("Instance physics is: \(samplemaths.physics)")  print("Instance formulae is: \(samplemaths.formulae)")  var chemCount = 0  var mathsCount = 0  for item in sa {  if item isChemistry {        ++chemCount     } elseif item isMaths {        ++mathsCount     }  }  print("Subjects in chemistry contains \(chemCount) topics and maths contains \(mathsCount) topics") The output for the above program would be Instance physics is: solid physics  Instance equation is: Hertz  Instance physics is: Fluid Dynamics  Instance formulae is: Giga Hertz  Subjects in chemistry contains 2 topics and maths contains 3 topics Downcasting Two operators (as? and as!) can be used to downcast the subclass type.In case the nil value gets returned the ‘as? , the operator returns an optional value.  It is used to monitor downcast success. The as! Operator is used for forced unwrapping in the context of optional chaining when downcasting returns nil value. It is used in case of downcast failure to trigger runtime errors classSubjects { var physics: String    init(physics: String) { self.physics = physics    } } classChemistry: Subjects { var equations: String    init(physics: String, equations: String) { self.equations = equations super.init(physics: physics)    } } classMaths: Subjects { var formulae: String    init(physics: String, formulae: String) { self.formulae = formulae super.init(physics: physics)    } } let sa = [ Chemistry(physics: "solid physics", equations: "Hertz"), Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"), Chemistry(physics: "Thermo physics", equations: "Decibels"), Maths(physics: "Astro Physics", formulae: "MegaHertz"), Maths(physics: "Differential Equations", formulae: "Cosine Series")] let samplechem = Chemistry(physics: "solid physics", equations: "Hertz") print("Instance physics is: \(samplechem.physics)") print("Instance equation is: \(samplechem.equations)") let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz") print("Instance physics is: \(samplemaths.physics)") print("Instance formulae is: \(samplemaths.formulae)") var chemCount = 0 var mathsCount = 0 for item in sa { ifletprint = item as? Chemistry { print("Chemistry topics are: '\(print.physics)', \(print.equations)")    } elseiflet example = item as? Maths { print("Maths topics are: '\(example.physics)', \(example.formulae)")    } } The above program output would be  Instance physics is: solid physics Instance equation is: Hertz Instance physics is: Fluid Dynamics Instance formulae is: Giga Hertz Chemistry topics are: 'solid physics', Hertz Maths topics are: 'Fluid Dynamics', Giga Hertz Chemistry topics are: 'Thermo physics', Decibels Maths topics are: 'Astro Physics', MegaHertz Maths topics are: 'Differential Equations', Cosine Series Typecasting: Any and Any Object The keyword 'Any' is used to represent an instance which belongs to any type including function types. For representing an instance of any type including function we use ‘Any’ keyword. classSubjects {  var physics: String     init(physics: String) {  self.physics = physics     }  }  classChemistry: Subjects {  var equations: String     init(physics: String, equations: String) {  self.equations = equations  super.init(physics: physics)     }  }  classMaths: Subjects {  var formulae: String     init(physics: String, formulae: String) {  self.formulae = formulae  super.init(physics: physics)     }  }  let sa = [  Chemistry(physics: "solid physics", equations: "Hertz"),  Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),  Chemistry(physics: "Thermo physics", equations: "Decibels"),  Maths(physics: "Astro Physics", formulae: "MegaHertz"),  Maths(physics: "Differential Equations", formulae: "Cosine Series")]  let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")  print("Instance physics is: \(samplechem.physics)")  print("Instance equation is: \(samplechem.equations)")  let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")  print("Instance physics is: \(samplemaths.physics)")  print("Instance formulae is: \(samplemaths.formulae)")  var chemCount = 0  var mathsCount = 0  for item in sa {  ifletprint = item as? Chemistry {  print("Chemistry topics are: '\(print.physics)', \(print.equations)")     } elseiflet example = item as? Maths {  print("Maths topics are: '\(example.physics)', \(example.formulae)")     }  }  var exampleany = [Any]()  exampleany.append(12)  exampleany.append(3.14159)  exampleany.append("Example for Any")  exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))  forprintin exampleany {  switchprint {  caselet someInt asInt:  print("Integer value is \(someInt)")  caselet someDouble asDoublewhere someDouble > 0:  print("Pi value is \(someDouble)")  caselet someString asString:  print("\(someString)")  caselet phy asChemistry:     print("Topics '\(phy.physics)', \(phy.equations)")  default:  print("None")     }  } The output for the above program would be the following: Instance physics is: solid physics  Instance equation is: Hertz  Instance physics is: Fluid Dynamics  Instance formulae is: Giga Hertz  Chemistry topics are: 'solid physics', Hertz  Maths topics are: 'Fluid Dynamics', Giga Hertz  Chemistry topics are: 'Thermo physics', Decibels  Maths topics are: 'Astro Physics', MegaHertz  Maths topics are: 'Differential Equations', Cosine Series  Integer value is 12  Pi value is 3.14159  Example for Any  Topics 'solid physics', Hertz AnyObject The ‘AnyObject’ keyword is used for representing an instance of any class type. classSubjects {  var physics: String     init(physics: String) {  self.physics = physics     }  }  classChemistry: Subjects {  var equations: String     init(physics: String, equations: String) {  self.equations = equations  super.init(physics: physics)     }  }  classMaths: Subjects {  var formulae: String     init(physics: String, formulae: String) {  self.formulae = formulae  super.init(physics: physics)     }  }  let saprint: [AnyObject] = [Chemistry(physics: "solid physics", equations: "Hertz"),  Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),  Chemistry(physics: "Thermo physics", equations: "Decibels"),  Maths(physics: "Astro Physics", formulae: "MegaHertz"),  Maths(physics: "Differential Equations", formulae: "Cosine Series")]  let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")  print("Instance physics is: \(samplechem.physics)")  print("Instance equation is: \(samplechem.equations)")  let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")  print("Instance physics is: \(samplemaths.physics)")  print("Instance formulae is: \(samplemaths.formulae)")  var chemCount = 0  var mathsCount = 0  for item in saprint {  ifletprint = item as? Chemistry {  print("Chemistry topics are: '\(print.physics)', \(print.equations)")     } elseiflet example = item as? Maths {  print("Maths topics are: '\(example.physics)', \(example.formulae)")     }  }  var exampleany = [Any]()  exampleany.append(12)  exampleany.append(3.14159)  exampleany.append("Example for Any")  exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))  forprintin exampleany {  switchprint {  caselet someInt asInt:  print("Integer value is \(someInt)")  caselet someDouble asDoublewhere someDouble > 0:  print("Pi value is \(someDouble)")  caselet someString asString:  print("\(someString)")  caselet phy asChemistry:  print("Topics '\(phy.physics)', \(phy.equations)")  default:  print("None")     }  } The output for the above program would be Instance physics is: solid physics  Instance equation is: Hertz  Instance physics is: Fluid Dynamics  Instance formulae is: Giga Hertz  Chemistry topics are: 'solid physics', Hertz  Maths topics are: 'Fluid Dynamics', Giga Hertz  Chemistry topics are: 'Thermo physics', Decibels  Maths topics are: 'Astro Physics', MegaHertz  Maths topics are: 'Differential Equations', Cosine Series  Integer value is 12  Pi value is 3.14159  Example for Any  Topics 'solid physics', HertzExtensions Extensions in a layman’s language add to a class, structure, enumeration or type of protocol new functionality. This even includes the feasibility to extend types for which the original source code is not even available (called retroactive modeling). Extensions in Swift are exactly the same as categories in Objective-C.Swift extension within the  functionalities : Adding of the computed instance properties along with computed type properties. Defining both the instance methods and type methods. Providing a new i:e non existing initializers. Defines the subscripts. Define and even validates the new nested types. Making an existing type adhering  to a protocol. Syntax extension SomeType {     // new functionality can be added here  } Existing type can also be added as a protocol standard with extensions and its syntax is similar to the classes or structures. extension SomeType: SomeProtocol, AnotherProtocol {     // protocol requirements is described here  } Computed Properties With the help of extensions computed ‘instance’ and type properties can be extended. extension Int {  varadd: Int {returnself + 100 }  varsub: Int { returnself - 10 }  var mul: Int { returnself * 10 }  var div: Int { returnself / 5 }  }  let addition = 3.add  print("Addition is \(addition)")  let subtraction = 120.sub  print("Subtraction is \(subtraction)")  let multiplication = 39.mul  print("Multiplication is \(multiplication)")  let division = 55.div  print("Division is \(division)")  let mix = 30.add + 34.sub  print("Mixed Type is \(mix)") The above program output would be Addition is 103  Subtraction is 110  Multiplication is 390  Division is 11  Mixed Type is 154 Initializers Swift offers the flexibility of adding new initializers by extensions to an existing type. The user can add his own custom types to extend the defined types and also allow further initialization options. Only init() is supported by extensions. The deinit() are not supported by extensions. struct sum {  var num1 = 100, num2 = 200  }  struct diff {  var no1 = 200, no2 = 100  }  struct mult {  var a = sum()  var b = diff()  }  let calc = mult()  print ("Inside mult block \(calc.a.num1, calc.a.num2)")  print("Inside mult block \(calc.b.no1, calc.b.no2)")  let memcalc = mult(a: sum(num1: 300, num2: 500),b: diff(no1: 300, no2: 100))  print("Inside mult block \(memcalc.a.num1, memcalc.a.num2)")  print("Inside mult block \(memcalc.b.no1, memcalc.b.no2)")  extension mult {     init(x: sum, y: diff) {  let X = x.num1 + x.num2  let Y = y.no1 + y.no2     }  }  let a = sum(num1: 100, num2: 200)  print("Inside Sum Block:\( a.num1, a.num2)")  let b = diff(no1: 200, no2: 100)  print("Inside Diff Block: \(b.no1, b.no2)")  The output for the above program would be  Inside mult block (100, 200)  Inside mult block (200, 100)  Inside mult block (300, 500)  Inside mult block (300, 100)  Inside Sum Block:(100, 200)  Inside Diff Block: (200, 100) Methods The extensions also help subclasses to add new instance methods and type methods. extension Int {     func topics(summation: () -> ()) {  for _ in0..<self {           summation()        }     }  }  4.topics(summation: {  print("Inside Extensions Block")  })  3.topics(summation: {  print("Inside Type Casting Block")  }) The output for the above program would be Inside Extensions Block  Inside Extensions Block  Inside Extensions Block  Inside Extensions Block  Inside Type Casting Block  Inside Type Casting Block  Inside Type Casting BlockMutating Instance Methods When declared as extensions, instance methods can also be mutated. Structures and enumeration methods that modify themselves or their properties must identify the instance method as mutating, as do methods from the original implementation. extension Double {     mutating func square() {  let pi = 3.1415  self = pi * self * self     }  }  varTrial1 = 3.3  Trial1.square()  print("Area of circle is: \(Trial1)")  varTrial2 = 5.8  Trial2.square()  print("Area of circle is: \(Trial2)")  varTrial3 = 120.3  Trial3.square()  print("Area of circle is: \(Trial3)")Subscript & Nested type extension Int {     subscript(var multtable: Int) -> Int {  var no1 = 1  while multtable > 0 {           no1 *= 10           --multtable        }  return (self / no1) % 10     }  }  print(12[0])  print(7869[1])  print(786543[2]) The extensions can help in extending nested types for class,structure and enumeration instance. extension Int {  enum calc {  caseadd  casesub  case mult  case div  case anything     }  varprint: calc {  switchself {  case0:  return .add  case1:  return .sub  case2:  return .mult  case3:  return .div  default:  return .anything        }     }  }  func result(numb: [Int]) {  for i in numb {  switch i.print {  case .add:  print(" 10 ")  case .sub:  print(" 20 ")  case .mult:  print(" 30 ")  case .div:  print(" 40 ")  default:  print(" 50 ")        }     }  }  result(numb: [0, 1, 2, 3, 4, 7]) Protocols A protocol defines the actual blueprint of any methods, its properties along with  other requirements which are perfectly suitable for a specific task or feature. Any class enumeration or structure can then take the protocol to ensure its actual execution. Any type of protocol complying with the requirements is said to comply with that protocol.You can extend the protocol to implement some of these needs and can also  implement additional functionality which conforms the types that  can be used.  Along with that it can even specify requirements that conform types that are a must for implementation. Syntax protocol SomeProtocol {     // protocol definition   } Protocols are declared after names of class, structure or type of enumeration. It is also feasible to declare single and multiple protocols. When defining various protocols, they must be split up by commas. structSomeStructure: Protocol1, Protocol2 {  // structure definition   } If a protocol for superclass has to be defined, the name of the protocol should follow the name of  Super Class with commas. class SomeClass: SomeSuperclass, Protocol1, Protocol2 {     // class definition   }Property and Method Requirements A protocol is used to indicate a property of instance or instance of specific class type. It simply specifies the property of the type or instance alone, instead of whether it has been stored or computed property. It is also used to indicate if the property is 'gettable' or 'settable'. ‘var' keyword declares property requirements as property variables. After their type declaration,{ get set} is used for declaring gettable and settable properties. Gettable is specified after a type declaration by{ get} property. protocol classa {  var marks: Int { getset }  var result: Bool { get }     func attendance() -> String     func markssecured() -> String  }  protocol classb: classa {  var present: Bool { getset }  var subject: String { getset }  var stname: String { getset }  }  class classc: classb {  var marks = 96  let result = true  var present = false  var subject = "Swift Protocols"  var stname = "Protocols"     func attendance() -> String {  return"The \(stname) has secured 99% attendance"     }     func markssecured() -> String {  return"\(stname) has scored \(marks)"     }  }  let studdet = classc()  studdet.stname = "Swift"  studdet.marks = 98  studdet.markssecured()  print(studdet.marks)  print(studdet.result)  print(studdet.present)  print(studdet.subject)  print(studdet.stname) The output for the above program would be  98  true  false  Swift  Protocols  Swift Mutating Method Requirements protocol daysofaweek {     mutating func print()  }  enum days: daysofaweek {  case sun, mon, tue, wed, thurs, fri, sat      mutating func print() {  switchself {  case sun:  self = sun  print("Sunday")  case mon:  self = mon  print("Monday")  case tue:  self = tue  print("Tuesday")  case wed:  self = wed  print("Wednesday")  case mon:  self = thurs  print("Thursday")  case tue:  self = fri  print("Friday")  case sat:  self = sat  print("Saturday")  default:  print("NO Such Day")        }     }  }  var res = days.wed  res.print() Initializer Requirements Swift allows users to initialize protocols that conform like normal initializers to type compliance. Syntax protocol SomeProtocol {     init(someParameter: Int)  }  Example  protocol tcpprotocol {     init(aprot: Int)  } Class Implementations of Protocol Initializer Requirements To initialize a protocol,designated or convenience initializer allows the user to conform its standard by reserved ‘required’ keyword. lass SomeClass: SomeProtocol {     required init(someParameter: Int) {  // initializer implementation statements     }  }  protocol tcpprotocol {     init(aprot: Int)  }  class tcpClass: tcpprotocol {     required init(aprot: Int) {     }  } Conformity to the Protocol is guaranteed on all subclasses with a "required" modifier for explicit or inherited execution.When a subclass overrides its superclass initialization requirement, the' override' keyword is used. protocol tcpprotocol {     init(no1: Int)  }  class mainClass {  var no1: Int// local storage     init(no1: Int) {  self.no1 = no1  // initialization     }  }  class subClass: mainClass, tcpprotocol {  var no2: Int     init(no1: Int, no2 : Int) {  self.no2 = no2  super.init(no1:no1)     }  // Requires only one parameter for convenient method     required override convenience init(no1: Int) {  self.init(no1:no1, no2:0)     }  }  let res = mainClass(no1: 20)  letprint = subClass(no1: 30, no2: 50)  print("res is: \(res.no1)")  print("res is: \(print.no1)")  print("res is: \(print.no2)")Protocols as Types Protocols are used as types of functions , classes, methods, etc, instead of applying functionality in a protocol. There are numerous ways in which protocols can be applicable : The basic one includes the Function, method or can even initialize as a parameter or return type As a constant, variable or property Even as Arrays, dictionaries or other containers and as items. protocol Generator {     typealias members     func next() -> members?  }  var items = [10,20,30].generate()  whilelet x = items.next() {  print(x)  }  for lists in map([1,2,3], {i in i*5}) {  print(lists)  }  print([100,200,300])  print(map([1,2,3], {i in i*10})) The output for the above program would be 10  20  30  5  10  15  [100, 200, 300]  [10, 20, 30] Adding Protocol Conformance with an Extension By using extensions, the existing type can be embraced and complied with by a fresh protocol. The existing type can be supplemented by extensions with new properties, methods, and subscripts. protocol AgeClasificationProtocol {  var age: Int { get }     func agetype() -> String  }  classPerson {  let firstname: String  let lastname: String  var age: Int     init(firstname: String, lastname: String) {  self.firstname = firstname  self.lastname = lastname  self.age = 10     }  }  extension Person : AgeClasificationProtocol {     func fullname() -> String {  var c: String        c = firstname + " " + lastname  return c     }     func agetype() -> String {  switch age {  case0...2:  return"Baby"  case2...12:  return"Child"  case13...19:  return"Teenager"  caselet x where x > 65:  return"Elderly"  default:  return"Normal"        }     }  }Protocol Inheritance Swift permits protocols to inherit properties that have been defined. It's comparable to class inheritance , but with several inheritance protocols separated by commas being listed. protocol classa {  var no1:Int{getset}     func calc(sum:Int)  }  protocol result {     func print(target: classa)  }  class student2: result {     func print(target: classa){        target.calc(sum:1)  }  }  class classb: result {     func print(target: classa){        target.calc(sum:5)  }  }  class student: classa {  var no1:Int=10     func calc(sum:Int){        no1 -= sum  print("Student attempted \(sum) times to pass")  if no1 <=0{  print("Student is absent for exam")  }  }  }  classPlayer{  var stmark: result!     init(stmark: result){  self.stmark = stmark  }     func print(target: classa){        stmark.print(target: target)  }  }  var marks =Player(stmark: student2())  var marksec = student()  marks.print(target: marksec)  marks.print(target: marksec)  marks.print(target: marksec)  marks.stmark = classb()  marks.print(target: marksec)  marks.print(target: marksec)  marks.print(target: marksec) The above program output would be  Student attempted 1 times to pass  Student attempted 1 times to pass  Student attempted 1 times to pass  Student attempted 5 times to pass  Student attempted 5 times to pass  Student is absent for exam  Student attempted 5 times to pass  Student is absent for exam Class Only Protocols When protocols and class protocols are described, the user needs to add class first followed by the inheritance list of protocols. rotocol tcpprotocol {     init(no1: Int)  }  class mainClass {  var no1: Int// local storage     init(no1: Int) {  self.no1 = no1  // initialization     }  }  class subClass: mainClass, tcpprotocol {  var no2: Int     init(no1: Int, no2 : Int) {  self.no2 = no2  super.init(no1:no1)     }  // Requires only one parameter for convenient method     required override convenience init(no1: Int) {  self.init(no1:no1, no2:0)     }  }  let res = mainClass(no1: 20)  letprint = subClass(no1: 30, no2: 50)  print("res is: \(res.no1)")  print("res is: \(print.no1)")  print("res is: \(print.no2)") Protocol composition The protocol composition can help multiple protocols to be called at once. Syntax protocol<SomeProtocol, AnotherProtocol>  Example  protocol stname {  var name:String{get}  }  protocol stage {  var age:Int{get}  }  structPerson: stname, stage {  var name:String  var age:Int  }  func print(celebrator: stname & stage){  print("\(celebrator.name) is \(celebrator.age) years old")  }  let studname =Person(name:"Priya", age:21)  print(studname)  let stud =Person(name:"Rehan", age:29)  print(stud)  let student =Person(name:"Roshan", age:19)  print(student) Checking for Protocol ConformanceYou can use the operators "is" and "as" defined in the type casting to verify protocol compliance and cast them into a particular protocol. The checking and casting on a protocol is identical to checking and casting to a type. The value of operator returns is visible as  true if an instance conforms to a protocol and returns false if it doesn’t. The as? version of the downcast operator always returns the optional value of the protocol’s type, and this value is actually nil if the instance doesn’t conform to that particular protocol. The as! version of the downcast operator even forces the downcast to the protocol type and activates a runtime error in the scenario where the downcast doesn’t succeed. importFoundation @objc protocol rectangle {  var area: Double { get }  }  @objcclassCircle: rectangle {  let pi = 3.1415927  var radius: Double  var area: Double { return pi * radius * radius }     init(radius: Double) { self.radius = radius }  }  @objcclass result: rectangle {  var area: Double     init(area: Double) { self.area = area }  }  class sides {  var rectsides: Int     init(rectsides: Int) { self.rectsides = rectsides }  }  let objects: [AnyObject] = [Circle(radius: 2.0),result(area:198),sides(rectsides: 4)]  forobjectin objects {  iflet objectWithArea = objectas? rectangle {  print("Area is \(objectWithArea.area)")     } else {  print("Rectangle area is not defined")     }  } The output for the above program would be Area is 12.5663708  Area is 198.0  Rectangle area is not definedGenericGeneric code allows you to write flexible, reusable functions and type, depending on criteria that you define, that can work with any type. You can write code which prevents duplication and clearly, abstractly expresses its purpose.Generics are one of Swift's strongest characteristics and many Swift standard libraries are made from generic code. Swift's Array and Dictionary are generic collections, for instance. You can generate an array containing Int or an array containing String values or a set for any other type in Swift. Likewise, you can generate a dictionary to store any given type of values and there are no restrictions on what type.func exchange(a: inout Int, b: inout Int) {  let temp = a     a = b     b = temp  }  var numb1 = 100  var numb2 = 200  print("Before Swapping values are: \(numb1) and \(numb2)")  exchange(a: &numb1, b: &numb2)  print("After Swapping values are: \(numb1) and \(numb2)") The output for the above program would be Before Swapping values are: 100 and 200  After Swapping values are: 200 and 100  Generic Functions: Type Parameters  Generic functions can be used to access any data type like 'Int' or 'String'.  func exchange<T>(a: inout T, b: inout T) {  let temp = a     a = b     b = temp  }  var numb1 = 100  var numb2 = 200  print("Before Swapping Int values are: \(numb1) and \(numb2)")  exchange(a: &numb1, b: &numb2)  print("After Swapping Int values are: \(numb1) and \(numb2)")  var str1 = "Generics"  var str2 = "Functions"  print("Before Swapping String values are: \(str1) and \(str2)")  exchange(a: &str1, b: &str2)  print("After Swapping String values are: \(str1) and \(str2)") The output for the above program would be  Before Swapping Int values are: 100 and 200  After Swapping Int values are: 200 and 100  Before Swapping String values are: Generics and Functions  After Swapping String values are: Functions and Generics The exchange() function is used to exchange values outlined above, and < T > is used as a parameter sort. The exchange() function is called first to return the value of' Int' and then the second call to the exchange() function gives the value of' String.' Inside the angle brackets, separated by commas, several parameter types can be included. The user-specified parameters of the type are named to understand what type of parameter it holds. As a generic parameter type name, Swift offers < T>. However, parameters such as Arrays and Dictionaries can be used to define that they are of the' Dictionary' type. struct TOS<T> {  var items = [T]()     mutating func push(item: T) {        items.append(item)     }     mutating func pop() -> T {  return items.removeLast()     }  }  var tos = TOS<String>()  tos.push(item: "Swift ")  print(tos.items)  tos.push(item: "Generics")  print(tos.items)  tos.push(item: "Type Parameters")  print(tos.items)  tos.push(item: "Naming Type Parameters")  print(tos.items)  let deletetos = tos.pop() The output for the above program  would be  [Swift ]  [Swift , Generics]  [Swift , Generics, Type Parameters]  [Swift , Generics, Type Parameters, Naming Type Parameters] Extending a Generic Type Extending the stack property to know the top of the item is included with 'extension' keyword. struct TOS<T> {  var items = [T]()     mutating func push(item: T) {        items.append(item)     }     mutating func pop() -> T {  return items.removeLast()     }  }  var tos = TOS<String>()  tos.push(item: "Swift ")  print(tos.items)  tos.push(item: "Generics")  print(tos.items)  tos.push(item: "Type Parameters")  print(tos.items)  tos.push(item: "Naming Type Parameters")  print(tos.items)  extension TOS {  var first: T? {  return items.isEmpty ? nil : items[items.count - 1]     }  }  iflet first = tos.first {  print("The top item on the stack is \(first).")  } The output for the above program would be ["Swift "]  ["Swift ", "Generics"]  ["Swift ", "Generics", "Type Parameters"]  ["Swift ", "Generics", "Type Parameters", "Naming Type Parameters"]  The top item on the stack is Naming Type Parameters. Type Constraints Specifically,' type constraints’' may allow the specified type parameter to be inherited from a certain class, or the protocol conformity standard to be ensured. func exchange<T>(a: inout T, b: inout T) {  let temp = a     a = b     b = temp  }  var numb1 = 100  var numb2 = 200  print("Before Swapping Int values are: \(numb1) and \(numb2)")  exchange(a: &numb1, b: &numb2)  print("After Swapping Int values are: \(numb1) and \(numb2)")  var str1 = "Generics"  var str2 = "Functions"  print("Before Swapping String values are: \(str1) and \(str2)")  exchange(a: &str1, b: &str2)  print("After Swapping String values are: \(str1) and \(str2)") The output for the above program would be Before Swapping Int values are: 100 and 200  After Swapping Int values are: 200 and 100  Before Swapping String values are: Generics and Functions  After Swapping String values are: Functions and GenericsAssociated Types In the protocol definition, Swift allows associated types to be declared by the' associatedtype' keyword. protocol Container {     associatedtype ItemType     mutating func append(item: ItemType)  var count: Int { get }     subscript(i: Int) -> ItemType { get }  }  struct TOS<T>: Container {  // original Stack<T> implementation  var items = [T]()     mutating func push(item: T) {        items.append(item)     }     mutating func pop() -> T {  return items.removeLast()     }  // conformance to the Container protocol     mutating func append(item: T) {  self.push(item: item)     }  var count: Int {  return items.count     }     subscript(i: Int) -> T {  return items[i]     }  }  var tos = TOS<String>()  tos.push(item: "Swift 4")  print(tos.items)  tos.push(item: "Generics")  print(tos.items)  tos.push(item: "Type Parameters")  print(tos.items)  tos.push(item: "Naming Type Parameters")  print(tos.items) The output for the above program would beAccess Control:Access control limits access by other source files and modules to parts of your code from the code. This feature assists the user to hide the implementation details of the user code, and to specify a particular interface through which that code can be accessed and easily used by the end users. In addition to offering different levels of control of access, Swift reduces the requirement for explicit levels of access control by providing standard access levels for typical scenarios. Module and abstraction are done through access control to restrict access to code blocks. According to their properties, methods, initializers and subscriptions, access to classes, structures and enumerations can be achieved through access control procedures. Access control is applicable to properties, types and functions can be referred to as 'entities'. Constants, variables and functions are restricted in a protocol and allowed access as global or local by way of access control. Modules and source files are the basis of the Access Control Model. The module is described as a single distribution unit of code and can be exported using an 'import' keyword. A single source file with multiple types and features in a module is defined as the source file. Three different types of access provided by Swift language  are: Public, Internal and Private Public: It is considered as the least restrictive access.  This type of access enables an entity to be accessed outside defining module.          Internal: It enables the use of entities within any source file of their module, but not outside that module in any source file. Private: It is classified as the most restrictive access. This type of access hides the implementation details of defining  module. Syntax: public class SomePublicClass {}  internal class SomeInternalClass {}  private class SomePrivateClass {}  public var somePublicVariable = 0  internal let someInternalConstant = 0  private func somePrivateFunction() {}Access control for function types: Some functions may even have their arguments being declared within the function without any return values. Such programs declare a and b as arguments to the sum() function. Within the function itself the values for the arguments a and b are fed by invoking the function call sum() and its values are automatically printed; thereby completely eliminating the return values. Inorder to make the function's return type as private, the end user declares the function’s overall access level with a private modifier. Live demo for the same would be: private func sum(a: Int, b: Int) {  let a = a + b  let b = a - b  print(a, b)  }  sum(a: 20, b: 10)  sum(a: 40, b: 10)  sum(a: 24, b: 6) The output achieved in this case is  30 20  50 40  30 24 Access Control for Enumeration Types: Live Demo  publicenumStudent {  caseName(String)  caseMark(Int,Int,Int)  }  var studDetails = Student.Name("Swift 4")  var studMarks = Student.Mark(98,97,95)  switch studMarks {  case .Name(let studName):  print("Student name is: \(studName).")  case .Mark(letMark1, letMark2, letMark3):  print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")  } While running this program with the playground we achieve the following output: Student Marks are: 98,97,95 For individual cases of an enumeration, the listing in Swift 4 automatically receives the same level of access. Consider accessing the name and trademarks of students in three subjects, for example. Enumerated names are declared as students and members of the enum class are names of a data type string, mark 2, and mark3 of an Integer data type. They have entered either the name of the student or the marks. Now, if that case block is carried out, the switch case will print out the name of the student. If both conditions fail, the default block will be executed.Access control of Subclasses: Swift 4 enables the user to subclass any class accessible in the existing access framework. A subclass cannot be greater than its superclass access level. A public subclass of an internal superclass is limited for the user. publicclass cricket {  internal func printIt() {  print("Welcome to Swift 4 Super Class")     }  }  internalclass tennis: cricket {  overrideinternal func printIt() {  print("Welcome to Swift 4 Sub Class")     }  }  let cricinstance = cricket()  cricinstance.printIt()  let tennisinstance = tennis()  tennisinstance.printIt() On running the above program with the playground, the following output can be achieved: Welcome to Swift Super Class  Welcome to Swift Sub ClassAccess Control for Constants, variables, properties, and subscripts: Swift 4 is not defined as the public constant, variable, or characteristic other than the type. A public property with a personal form is not valid to be documented. More so, a subscript cannot be more public in comparison to its index or return type. If a constant, variable, property or subscript uses a private form, it must also be labeled privately as a constant, variable, property or subscription private var privateInstance = SomePrivateClass() Getters and Setters: The same access levels are automatically received by getters and setters of constant, variable, properties and subscript to which they actually belong to. class Samplepgm {  var counter: Int = 0{        willSet(newTotal) {  print("Total Counter is: \(newTotal)")        }        didSet {  if counter > oldValue {  print("Newly Added Counter \(counter - oldValue)")           }        }     }  }  letNewCounter = Samplepgm()  NewCounter.counter = 100  NewCounter.counter = 800 The output of the above program is shown below: Total Counter is: 100  Newly Added Counter 100  Total Counter is: 800  Newly Added Counter 700Access Control for Initializers and Default Initializers: Custom initializers can actually be assigned the access less than or equal to the initialized type.The required initializer must have the same amount of access as its class. The types of parameters of an initializer cannot be more private than the access level of the initializer itself. For declaration of each and every subclass of the initialize,the 'required' keyword needs to be pre-defined prior the init() function. class classA {     required init() {  let a = 10  print(a)     }  }  class classB: classA {     required init() {  let b = 30  print(b)     }  }  let res = classA()  letprint = classB() Following outputs are obtained by running the above program: 10  30  10 A default initializer has the same level of access as its initialised type, unless that type is publicly defined.If initializing by default is public, it is internally considered. If the user needs to have a public type initialized in another module with a no-argument initializer, it provides exclusively a public no-argument initializer as part of the type's definition.Access control for Protocols:  The same levels of access to each other must be stated when defining a new protocol to inherit functions from the existing prototype.The Swift 4 access control will not enable users inherent in an 'internal' protocol to define a 'public' protocol. public protocol tcpprotocol {     init(no1: Int)  }  publicclass mainClass {  var no1: Int// local storage     init(no1: Int) {  self.no1 = no1 // initialization     }  }  class subClass: mainClass, tcpprotocol {  var no2: Int     init(no1: Int, no2 : Int) {  self.no2 = no2  super.init(no1:no1)     }  // Requires only one parameter for convenient method     required override convenience init(no1: Int) {  self.init(no1:no1, no2:0)     }  }  let res = mainClass(no1:20)  let print = subClass(no1:30, no2:50)  print("res is: \(res.no1)")  print("res is: \(print.no1)")  print("res is: \(print.no2)") While running the program, the following output is being achieved: res is: 20  res is: 30  res is: 50 Access Control for Extensions:Swift 4 does not entertain the end users to facilitate an explicit access level modifier for an extension when the user uses that particular extension to add protocol conformance. The default access level in case of every single protocol requirement actually does the implementation within the extension and  is provided with its very own protocol access level.Access Level for Generics:In case of Generics users are allowed to specify minimum access levels to access the type constraints along with its type parameters.public struct TOS<T> {  var items = [T]()     mutating func push(item: T) {        items.append(item)     }     mutating func pop() -> T {  return items.removeLast()     }  }  var tos = TOS<String>()  tos.push(item: "Swift 4")  print(tos.items)  tos.push(item: "Generics")  print(tos.items)  tos.push(item: "Type Parameters")  print(tos.items)  tos.push(item: "Naming Type Parameters")  print(tos.items)  let deletetos = tos.pop() The following results are obtained when the program is being run: [Swift 4]  [Swift 4, Generics]  [Swift 4, Generics, Type Parameters]  [Swift 4, Generics, Type Parameters, Naming Type Parameters] Access Control for Type Aliases:The user can readily define type aliases to treat the unique access control types, whereas the same or different access levels can be easily identified by the user. In scenarios wherein the type alias is 'private' its associated members can be declared as 'private, internal of public type', and in the situations wherein the type alias is public the members cannot be an alias as an 'internal' or 'private' name. Any type aliases defined are regarded as distinct types for the exclusive purposes of access control. A type alias can even have an access level less than or equal to the access level of the type its aliases have in original. For example, a private type alias can actually alias a private, internal, or public type in contrary to which  a public type alias cannot alias an internal or private type. public protocol Container {     associatedtype ItemType     mutating func append(item: ItemType)  var count: Int { get }     subscript(i: Int) -> ItemType { get }  }  structStack<T>: Container {  // original Stack<T> implementation  var items = [T]()     mutating func push(item: T) {        items.append(item)     }     mutating func pop() -> T {  return items.removeLast()     }  // conformance to the Container protocol     mutating func append(item: T) {  self.push(item: item)     }  var count: Int {  return items.count     }     subscript(i: Int) -> T {  return items[i]     }  }  func allItemsMatch<     C1: Container, C2: Container  where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>     (someContainer: C1, anotherContainer: C2) -> Bool {  // check that both containers contain the same number of items  if someContainer.count != anotherContainer.count {  returnfalse     }  // check each pair of items to see if they are equivalent  for i in0..<someContainer.count {  if someContainer[i] != anotherContainer[i] {  returnfalse        }     }  // all items match, so return true  returntrue  }  var tos = Stack<String>()  tos.push(item: "Swift 4")  print(tos.items)  tos.push(item: "Generics")  print(tos.items)  tos.push(item: "Where Clause")  print(tos.items)  var eos = ["Swift 4", "Generics", "Where Clause"]  print(eos) The following output is being achieved while the above program is being run: [Swift 4]  [Swift 4, Generics]  [Swift 4, Generics, Where Clause]  [Swift 4, Generics, Where Clause] Swift Encoding and Decoding: Swift 4 introduces the new Codable protocol, which allows you to serialize and remove customized data types without any special code – and without worrying about losing your value types. struct Language: Codable {  var name: String  var version: Int  }  let swift = Language(name: "Swift", version: 4)  let java = Language(name: "java", version: 8)  let R = Language(name: "R", version: 3  let encoder =JSONEncoder()  iflet encoded =try? encoder.encode(java){  //Perform some operations on this value.  }  let decoder =JSONDecoder()  iflet decoded =try? decoder.decode(Language.self,from: encoded){  //Perform some operations on this value.  } Summary:This module covered all other details related to ARC ,optional chaining ,type casting ,extensions ,protocols and generics. We have also got fair understanding of access control with help of this module.
logo

Swift Tutorial

Miscellaneous

  • ARC Overview 
  • Optional Chaining 
  • Type Casting 
  • Extensions 
  • Protocols 
  • Generics 
  • Access Control 

ARC Overview 

In order to monitor and handle the memory usage of your app, Swift utilizes Automatic Reference Counting (ARC). As a programmer, you are not required to think about memory management as it is being taken care of by ARC. If such instances are no longer required, ARC automatically releases the memory used by class instances. 

In a few instances, however, ARC needs further data on the connections between components of your code to handle your memory. 

ARC allocates a piece of memory for storing data every time you generate a fresh class instance . This memory contains data on the type of class and any stored characteristics connected with that instance. 

ARC assures an additional property of class instances which  no longer take up memory space when they are not required, and hence the space can be utilized for some other purposes. 

However, In case if ARC deallocates an instance that was already being used, the instance's properties would no longer be accessed. Infact , if  the user attempted to achieve the above kind of instance, the app would most probably crash. 

ARC monitors the number of properties , constants and variables presently referred to each class instance , to ensure that instances do not vanish as required. As long as at least one active reference exists still, ARC will not deallocate an instance.To enable this, property, constant or variable refers strongly to instance where the user assigns a class instance to a property, constant or variable. The reference is called a "strong" reference . It is being referred as strong here since the  instance does not allow it to be distributed for as long as it remains a same i:s“Strong reference”.

Example 

class Person { 
   let name: String 
   init(name: String) { 
       self.name = name 
       print("\(name) is being initialized") 
   } 
   deinit { 
       print("\(name) is being deinitialized") 
   } 
} 
ARC Strong Reference Cycles Class Instances 
class studmarks { 
let name:String 
var stud: student? 
   init (name:String){ 
print("Initializing: \(name)") 
self.name = name 
} 
   deinit { 
print("Deallocating: \(self.name)") 
} 
} 
class student { 
let name:String 
var strname: studmarks? 
   init (name:String){ 
print("Initializing: \(name)") 
self.name = name 
} 
   deinit { 
print("Deallocating: \(self.name)") 
} 
} 
var shiba: studmarks? 
var mari: student? 
shiba = studmarks(name:"Hello") 
mari = student(name:"ARC") 
shiba!.stud = anushka 
mari!.strname = Swati

ARC Weak and Unowned References 

These references are used to allow an individual instance in a reference process to refer to other instances. Instead of taking great care of the strong reference cycle, the instance may refer to every single instance. If the user understands that a certain instance can return nil, we can point out that the weak reference is used. If something is returned instead of nil, then declare it with an unknown reference. 

Weak Reference 

classmodule{ 
let name:String 
   init(name:String){self.name = name } 
varsub: submodule? 
   deinit {print("\(name) Is The Main Module")} 
} 
class submodule { 
let number:Int 
   init(number:Int){self.number = number } 
   weak var topic:module? 
   deinit {print("Sub Module with its topic number is \(number)")} 
} 
var toc:module? 
var list: submodule? 
toc =module(name:"ARC") 
list = submodule(number:4) 
toc!.sub= list 
list!.topic = toc 
toc =nil 
list =nil 


The output of the above program would be 

ARC Is The Main Module 
Sub Module with its topic number is 4

Unowned References 

class student { 
   let name: String 
   var section: marks? 
   init(name: String) { 
      self.name = name 
   } 
   deinit { print("\(name)") } 
} 
class marks { 
   let marks: Int 
   unowned let stname: student 
   init(marks: Int, stname: student) { 
      self.marks = marks 
      self.stname = stname 
   } 
   deinit { print("Marks Obtained by the student is \(marks)") } 
} 
var module: student? 
module = student(name: "ARC") 
module!.section = marks(marks: 98, stname: module!) 
module = nil 

The output of the above program would be 

ARC 
Marks Obtained by the student is 98

Strong Reference Cycles for Closures 

When we actually assign a closure statement to the class instance property and to the body of the closure to capture a particular instance ,there is a scope that the strong reference cycle can occur. Strong reference to the closure in particular is well addressed and defined as  by 'self.someProperty' or 'self.someMethod()'. Strong reference cycles are in turn used as reference types for the closures. 

The strong reference cycle can happen if a closure for the class instance property and the body of the closure is assigned in order to capture a specific instance. self.someProperty' or' self.someMethod()' is the strong reference to closure. As reference types for closures, strong reference cycles are used. 

class HTMLElement{ 
   let samplename:String 
   let text:String? 
   lazy var asHTML:()->String={ 
      if let text = self.text { 
         return "<\(self.samplename)>\(text)</\(self.samplename)>" 
} else { 
         return "<\(self.samplename) />" 
} 
} 
   init(samplename:String, text:String?= nil){ 
      self.samplename = samplename 
      self.text = text 
} 
   deinit { 
      print("\(samplename) is being deinitialized") 
} 
} 
var paragraph:HTMLElement?=HTMLElement(samplename:"p", text:"Welcome to Closure SRC") 
print(paragraph!.asHTML()) 
The output for the above program would be  
<p>Welcome to Closure SRC</p> 

Optional Chaining 

Optional chaining is an operation on an optional that could presently be nil for querying and calling properties, methods, and subscriptions. If the options include the value, the property, methods, or subscript call is successful, if the optional is nil, then nil returns the property, method or subscript call. Many queries can be linked together, and if any link is nil, the whole chain will fail gracefully. 

Optional Chaining as an Alternative to Forced Unwrapping 

If you want to call a property, method or subscript on optional value if you have an optional non-nil, you indicate optional chaining by putting the question mark(?). This is very comparable to a mark(!) after an optional value to force its value to be unwrapped. The major distinction is that if the optional is nil, optional chaining fails, whereas forced unwrapping causes a runtime error when the optional is nil. 

Program for optional chaining by (!) 

classLoksabhaPoll{ 
var candidate:Constituency? //Optional 
} 
lass Constituency{ 
var name ="Hajipur" 
} 
let cand =LoksabhaPoll () 
let candname = cand.candidate!.name //forced unwrapping 
The output for the above program would be as follows 
fatal error: unexpectedly found nil while unwrapping an Optional value 
0 Swift 4 0x0000000103410b68 
llvm::sys::PrintStackTrace(__sFILE*) + 40 
1 Swift 4 0x0000000103411054 SignalHandler(int) + 452 
2 libsystem_platform.dylib 0x00007fff9176af1a _sigtramp + 26 
3 libsystem_platform.dylib 0x000000000000000b _sigtramp + 1854492939 
4 libsystem_platform.dylib 0x00000001074a0214 _sigtramp + 1976783636 
5 Swift 4 0x0000000102a85c39 
llvm::JIT::runFunction(llvm::Function*, std::__1::vector > const&) + 329 
6 Swift 4 0x0000000102d320b3 
llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, 
std::__1::vector<std::__1::basic_string, std::__1::allocator >, 
std::__1::allocator<std::__1::basic_string, std::__1::allocator > > > const&, 
char const* const*) + 1523 
7 Swift 4 0x000000010296e6ba Swift 4::RunImmediately(Swift 
4::CompilerInstance&, std::__1::vector<std::__1::basic_string, 
std::__1::allocator >, std::__1::allocator<std::__1::basic_string, 
std::__1::allocator > > > const&, Swift 4::IRGenOptions&, Swift 4::SILOptions 
const&) + 1066 
8 Swift 4 0x000000010275764b frontend_main(llvm::ArrayRef, 
char const*, void*) + 5275 
9 Swift 4 0x0000000102754a6d main + 1677 
10 libdyld.dylib 0x00007fff8bb9e5c9 start + 1 
11 libdyld.dylib 0x000000000000000c start + 1950751300 
Stack dump: 
0.Program arguments:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/ 
usr/bin/Swift 4 -frontend -interpret - -target x86_64-apple-darwin14.0.0 - 
target-cpu core2 -sdk 
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/ 
SDKs/MacOSX10.10.sdk -module-name main 
/bin/sh: line 47: 15672 Done cat <<'SWIFT 4' 
import Foundation 
</std::__1::basic_string</std::__1::basic_string</std::__1::basic_string</std:: 
__1::basic_string 

Since the values are not stated in their base class, the value ' NIL' is saved and the force unwrapping operation returns a fatal error. 

Program for optional chaining by (?) 
classLoksabhaPoll{ 
var candidate:Constituency? //Optional 
} 
lass Constituency{ 
var name ="Hajipur" 
} 
let cand =LoksabhaPoll() 
if let candname = cand.candidate?.name { 
   print("Candidate name is \(candname)") 
} else { 
   print("Candidate name cannot be retrieved") 
} 
The output for the above program would be 
Candidate name cannot be retrieved 
Defining Model Classes for Optional Chaining & Accessing Properties 

Swift also offers the optional chaining idea in the form of declaring more than one subclass as a model class. This idea is very helpful for defining and accessing complicated models and sub-properties of properties, methods, and subscriptions. 

class rectangle { 
   var print: circle? 
} 
class circle { 
   var area =[radius]() 
   var cprint:Int{ 
      return area.count 
} 
   subscript(i:Int)-> radius { 
      get { 
         return area[i] 
} 
      set { 
         area[i]= newValue 
} 
} 
   func circleprint(){ 
      print("The number of rooms is \(cprint)") 
} 
   var rectarea: circumference? 
} 
class radius { 
   let radiusname:String 
   init(radiusname:String){ self.radiusname = radiusname } 
} 
class circumference { 
   var circumName:String? 
   var circumNumber:String? 
   var street:String? 
   func buildingIdentifier()->String?{ 
      if circumName != nil { 
         return circumName 
} else if circumNumber != nil { 
         return circumNumber 
} else { 
         return nil 
} 
} 
} 
let rectname = rectangle() 
if let rectarea = rectname.print?.cprint { 
   print("Area of rectangle is \(rectarea)") 
} else { 
   print("Rectangle Area is not specified") 
} 
The output for the above program would be  
Rectangle Area is not specified

Calling Methods Through Optional Chaining 

class rectangle { 
varprint: circle? 
} 
class circle { 
var area = [radius]() 
var cprint: Int { 
return area.count 
   } 
   subscript(i: Int) -> radius { 
get { 
return area[i] 
      } 
set { 
         area[i] = newValue 
      } 
   } 
   func circleprint() { 
print("Area of Circle is: \(cprint)") 
   } 
var rectarea: circumference? 
} 
class radius { 
let radiusname: String 
   init(radiusname: String) { self.radiusname = radiusname } 
} 
class circumference { 
var circumName: String? 
var circumNumber: String? 
var circumarea: String? 
   func buildingIdentifier() -> String? { 
if circumName != nil { 
return circumName 
      } elseif circumNumber != nil { 
return circumNumber 
      } else { 
returnnil 
      } 
   } 
} 
let circname = rectangle() 
if circname.print?.circleprint() != nil { 
print("Area of circle is specified)") 
} else { 
print("Area of circle is not specified") 
} 
.

In the circle () subclass, the function circleprint() is called when an instance 'circname' is created. If the function includes some value, the value is given back, it checks the value by checking 'circname.print?.circleprint() != nil’  to return some specified print message in case of nil.

Accessing Subscripts through Optional Chaining 

To set and retrieve a subscript value we can leverage optional chaining for ensuring whether a call to that subscript returns a value or not.The optional value of a specific subscript can be accessed by  putting before’?’ the subscript braces.

Example 1 

class rectangle { 
   var print: circle? 
} 
class circle { 
   var area =[radius]() 
   var cprint:Int{ 
      return area.count 
} 
   subscript(i:Int)-> radius { 
      get { 
         return area[i] 
} 
      set { 
         area[i]= newValue 
} 
} 
   func circleprint(){ 
      print("The number of rooms is \(cprint)") 
} 
   var rectarea: circumference? 
} 
class radius { 
   let radiusname:String 
   init(radiusname:String){ self.radiusname =  radiusname } 
} 
class circumference { 
   var circumName:String? 
   var circumNumber:String? 
   var circumarea:String? 
   func buildingIdentifier()->String?{ 
      if circumName != nil { 
         return circumName 
} else if circumNumber != nil { 
         return circumNumber 
} else { 
         return nil 
} 
} 
} 
let circname = rectangle() 
if let radiusName = circname.print?[0].radiusname { 
   print("The first room name is \(radiusName).") 
} else { 
   print("Radius is not specified.") 
} 
 The output of the above program would be

Radius is not specified. 

In the example above the membership function, 'radiusName' instance values are not specified.  

Example 2 

In the below example membership function instance values are specified. 

class rectangle { 
varprint: circle? 
} 
class circle { 
var area = [radius]() 
var cprint: Int { 
return area.count 
   } 
   subscript(i: Int) -> radius { 
get { 
return area[i] 
      } 
set { 
         area[i] = newValue 
      } 
   } 
   func circleprint() { 
print("The number of rooms is \(cprint)") 
   } 
var rectarea: circumference? 
} 
class radius { 
let radiusname: String 
   init(radiusname: String) { self.radiusname = radiusname } 
} 
class circumference { 
var circumName: String? 
var circumNumber: String? 
var circumarea: String? 
   func buildingIdentifier() -> String? { 
if circumName != nil { 
return circumName 
      } elseif circumNumber != nil { 
return circumNumber 
      } else { 
returnnil 
      } 
   } 
} 
let circname = rectangle() 
circname.print?[0] = radius(radiusname: "Diameter") 
let printing = circle() 
printing.area.append(radius(radiusname: "Units")) 
printing.area.append(radius(radiusname: "Meter")) 
circname.print = printing 
iflet radiusName = circname.print?[0].radiusname { 
print("Radius is measured in \(radiusName).") 
} else { 
print("Radius is not specified.") 
}

Accessing Subscripts of Optional Type 

class rectangle { 
varprint: circle? 
} 
class circle { 
var area = [radius]() 
var cprint: Int { 
return area.count 
   } 
   subscript(i: Int) -> radius { 
get { 
return area[i] 
      } 
set { 
         area[i] = newValue 
      } 
   } 
   func circleprint() { 
print("The number of rooms is \(cprint)") 
   } 
var rectarea: circumference? 
} 
class radius { 
let radiusname: String 
   init(radiusname: String) { self.radiusname = radiusname } 
} 
class circumference { 
var circumName: String? 
var circumNumber: String? 
var circumarea: String? 
   func buildingIdentifier() -> String? { 
if circumName != nil { 
return circumName 
      } elseif circumNumber != nil { 
return circumNumber 
      } else { 
returnnil 
      } 
   } 
} 
let circname = rectangle() 
circname.print?[0] = radius(radiusname: "Diameter") 
let printing = circle() 
printing.area.append(radius(radiusname: "Units")) 
printing.area.append(radius(radiusname: "Meter")) 
circname.print = printing 
var area = ["Radius": [35, 45, 78, 101], "Circle": [90, 45, 56]] 
area["Radius"]?[1] = 78 
area["Circle"]?[1]-- 
print(area["Radius"]?[0]) 
print(area["Radius"]?[1]) 
print(area["Radius"]?[2]) 
print(area["Radius"]?[3]) 
print(area["Circle"]?[0]) 
print(area["Circle"]?[1]) 
print(area["Circle"]?[2]) 
The output for the above program would be  
Optional(35) 
Optional(78) 
Optional(78) 
Optional(101) 
Optional(90) 
Optional(44) 
Optional(56)

Linking Multiple Levels of Chaining 

The optional chaining also facilitates multiple subclasses linking with its superclass properties, methods, and subscripts. 

class rectangle { 
varprint: circle? 
} 
class circle { 
var area = [radius]() 
var cprint: Int { 
return area.count 
   } 
   subscript(i: Int) -> radius { 
get { 
return area[i] 
      } 
set { 
         area[i] = newValue 
      } 
   } 
   func circleprint() { 
print("The number of rooms is \(cprint)") 
   } 
var rectarea: circumference? 
} 
class radius { 
let radiusname: String 
   init(radiusname: String) { self.radiusname = radiusname } 
} 
class circumference { 
var circumName: String? 
var circumNumber: String? 
var circumarea: String? 
   func buildingIdentifier() -> String? { 
if circumName != nil { 
return circumName 
      } elseif circumNumber != nil { 
return circumNumber 
      } else { 
returnnil 
      } 
   } 
} 
let circname = rectangle() 
iflet radiusName = circname.print?[0].radiusname { 
print("The first room name is \(radiusName).") 
} else { 
print("Radius is not specified.") 
} 

The instance values for the' radiusName' member function are not specified in the above program.It will return only else part of function, while returning values we need to define values for membership function. If the value we are trying to retrieve is optional, then optional chaining will also retrieve the optional value.  

class rectangle { 
varprint: circle? 
} 
class circle { 
var area = [radius]() 
var cprint: Int { 
return area.count 
   } 
   subscript(i: Int) -> radius { 
get { 
return area[i] 
      } 
set { 
         area[i] = newValue 
      } 
   } 
   func circleprint() { 
print("The number of rooms is \(cprint)") 
   } 
var rectarea: circumference? 
} 
class radius { 
let radiusname: String 
   init(radiusname: String) { self.radiusname = radiusname } 
} 
class circumference { 
var circumName: String? 
var circumNumber: String? 
var circumarea: String? 
   func buildingIdentifier() -> String? { 
if circumName != nil { 
return circumName 
      } elseif circumNumber != nil { 
return circumNumber 
      } else { 
returnnil 
      } 
   } 
} 
let circname = rectangle() 
circname.print?[0] = radius(radiusname: "Diameter") 
let printing = circle() 
printing.area.append(radius(radiusname: "Units")) 
printing.area.append(radius(radiusname: "Meter")) 
circname.print = printing 
iflet radiusName = circname.print?[0].radiusname { 
print("Radius is measured in \(radiusName).") 
} else { 
print("Radius is not specified.") 
} 

When we run the above program the output would be  

Radius is measured in Units.

Chaining on Methods with Optional Return Values 

The subclasses methods can be also accessed by optional chaining. 

class rectangle { 
varprint: circle? 
} 
class circle { 
var area = [radius]() 
var cprint: Int { 
return area.count 
   } 
   subscript(i: Int) -> radius { 
get { 
return area[i] 
      } 
set { 
         area[i] = newValue 
      } 
   } 
   func circleprint() { 
print("Area of Circle is: \(cprint)") 
   } 
var rectarea: circumference? 
} 
class radius { 
let radiusname: String 
   init(radiusname: String) { self.radiusname = radiusname } 
} 
class circumference { 
var circumName: String? 
var circumNumber: String? 
var circumarea: String? 
   func buildingIdentifier() -> String? { 
if circumName != nil { 
return circumName 
      } elseif circumNumber != nil { 
return circumNumber 
      } else { 
returnnil 
      } 
   } 
} 
let circname = rectangle() 
if circname.print?.circleprint() != nil { 
print("Area of circle is specified)") 
} else { 
print("Area of circle is not specified") 
} 

Type Casting 

Typecasting is a way of examining the type of instance or treating it as a superclass or subclass different from that of another one in its class hierarchy. The casting of type in Swift is carried out with operators ”is” and “as”. Both operators provide an easy and expressive way of checking a value type or casting a value to a different type.

Defining a Class Hierarchy 

Typecasting is used to check the type of instance to see if it belongs to a specific type of class. It also examines the class hierarchy and its subclasses in order to check and cast these instances in the same hierarchy. 

classSubjects { 
var physics: String 
   init(physics: String) { 
self.physics = physics 
   } 
} 
classChemistry: Subjects { 
var equations: String 
   init(physics: String, equations: String) { 
self.equations = equations 
super.init(physics: physics) 
   } 
} 
classMaths: Subjects { 
var formulae: String 
   init(physics: String, formulae: String) { 
self.formulae = formulae 
super.init(physics: physics) 
   } 
} 
let sa = [ Chemistry(physics: "solid physics", equations: "Hertz"), 
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")] 
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz") 
print("Instance physics is: \(samplechem.physics)") 
print("Instance equation is: \(samplechem.equations)") 
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz") 
print("Instance physics is: \(samplemaths.physics)") 
print("Instance formulae is: \(samplemaths.formulae)") 

The output for the above program would be  

Instance physics is: solid physics 
Instance equation is: Hertz 
Instance physics is: Fluid Dynamics 
Instance formulae is: Giga Hertz 

Type Checking 

The' is' operator will perform the type check. The' Is' type checks if the instance is a subclass-type instance and returns true if it belongs to this instance, otherwise it returns false. 

class Subjects { 
var physics: String 
   init(physics: String) { 
self.physics = physics 
   } 
} 
classChemistry: Subjects { 
var equations: String 
   init(physics: String, equations: String) { 
self.equations = equations 
super.init(physics: physics) 
   } 
} 
classMaths: Subjects { 
var formulae: String 
   init(physics: String, formulae: String) { 
self.formulae = formulae 
super.init(physics: physics) 
   } 
} 
let sa = [ 
Chemistry(physics: "solid physics", equations: "Hertz"), 
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"), 
Chemistry(physics: "Thermo physics", equations: "Decibels"), 
Maths(physics: "Astro Physics", formulae: "MegaHertz"), 
Maths(physics: "Differential Equations", formulae: "Cosine Series")] 
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz") 
print("Instance physics is: \(samplechem.physics)") 
print("Instance equation is: \(samplechem.equations)") 
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz") 
print("Instance physics is: \(samplemaths.physics)") 
print("Instance formulae is: \(samplemaths.formulae)") 
var chemCount = 0 
var mathsCount = 0 
for item in sa { 
if item isChemistry { 
      ++chemCount 
   } elseif item isMaths { 
      ++mathsCount 
   } 
} 
print("Subjects in chemistry contains \(chemCount) topics and maths contains \(mathsCount) topics") 

The output for the above program would be 

Instance physics is: solid physics 
Instance equation is: Hertz 
Instance physics is: Fluid Dynamics 
Instance formulae is: Giga Hertz 
Subjects in chemistry contains 2 topics and maths contains 3 topics 

Downcasting 

Two operators (as? and as!) can be used to downcast the subclass type.In case the nil value gets returned the ‘as? , the operator returns an optional value.  It is used to monitor downcast success. The as! Operator is used for forced unwrapping in the context of optional chaining when downcasting returns nil value. It is used in case of downcast failure to trigger runtime errors 

classSubjects { 
var physics: String 
   init(physics: String) { 
self.physics = physics 
   } 
} 
classChemistry: Subjects { 
var equations: String 
   init(physics: String, equations: String) { 
self.equations = equations 
super.init(physics: physics) 
   } 
} 
classMaths: Subjects { 
var formulae: String 
   init(physics: String, formulae: String) { 
self.formulae = formulae 
super.init(physics: physics) 
   } 
} 
let sa = [ 
Chemistry(physics: "solid physics", equations: "Hertz"), 
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"), 
Chemistry(physics: "Thermo physics", equations: "Decibels"), 
Maths(physics: "Astro Physics", formulae: "MegaHertz"), 
Maths(physics: "Differential Equations", formulae: "Cosine Series")] 
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz") 
print("Instance physics is: \(samplechem.physics)") 
print("Instance equation is: \(samplechem.equations)") 
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz") 
print("Instance physics is: \(samplemaths.physics)") 
print("Instance formulae is: \(samplemaths.formulae)") 
var chemCount = 0 
var mathsCount = 0 
for item in sa { 
ifletprint = item as? Chemistry { 
print("Chemistry topics are: '\(print.physics)', \(print.equations)") 
   } elseiflet example = item as? Maths { 
print("Maths topics are: '\(example.physics)', \(example.formulae)") 
   } 
} 

The above program output would be  

Instance physics is: solid physics 
Instance equation is: Hertz 
Instance physics is: Fluid Dynamics 
Instance formulae is: Giga Hertz 
Chemistry topics are: 'solid physics', Hertz 
Maths topics are: 'Fluid Dynamics', Giga Hertz 
Chemistry topics are: 'Thermo physics', Decibels 
Maths topics are: 'Astro Physics', MegaHertz 
Maths topics are: 'Differential Equations', Cosine Series 

Typecasting: Any and Any Object 

The keyword 'Any' is used to represent an instance which belongs to any type including function types. For representing an instance of any type including function we use ‘Any’ keyword. 

classSubjects { 
var physics: String 
   init(physics: String) { 
self.physics = physics 
   } 
} 
classChemistry: Subjects { 
var equations: String 
   init(physics: String, equations: String) { 
self.equations = equations 
super.init(physics: physics) 
   } 
} 
classMaths: Subjects { 
var formulae: String 
   init(physics: String, formulae: String) { 
self.formulae = formulae 
super.init(physics: physics) 
   } 
} 
let sa = [ 
Chemistry(physics: "solid physics", equations: "Hertz"), 
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"), 
Chemistry(physics: "Thermo physics", equations: "Decibels"), 
Maths(physics: "Astro Physics", formulae: "MegaHertz"), 
Maths(physics: "Differential Equations", formulae: "Cosine Series")] 
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz") 
print("Instance physics is: \(samplechem.physics)") 
print("Instance equation is: \(samplechem.equations)") 
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz") 
print("Instance physics is: \(samplemaths.physics)") 
print("Instance formulae is: \(samplemaths.formulae)") 
var chemCount = 0 
var mathsCount = 0 
for item in sa { 
ifletprint = item as? Chemistry { 
print("Chemistry topics are: '\(print.physics)', \(print.equations)") 
   } elseiflet example = item as? Maths { 
print("Maths topics are: '\(example.physics)', \(example.formulae)") 
   } 
} 
var exampleany = [Any]() 
exampleany.append(12) 
exampleany.append(3.14159) 
exampleany.append("Example for Any") 
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz")) 
forprintin exampleany { 
switchprint { 
caselet someInt asInt: 
print("Integer value is \(someInt)") 
caselet someDouble asDoublewhere someDouble > 0: 
print("Pi value is \(someDouble)") 
caselet someString asString: 
print("\(someString)") 
caselet phy asChemistry:    
print("Topics '\(phy.physics)', \(phy.equations)") 
default: 
print("None") 
   } 
} 

The output for the above program would be the following: 

Instance physics is: solid physics 
Instance equation is: Hertz 
Instance physics is: Fluid Dynamics 
Instance formulae is: Giga Hertz 
Chemistry topics are: 'solid physics', Hertz 
Maths topics are: 'Fluid Dynamics', Giga Hertz 
Chemistry topics are: 'Thermo physics', Decibels 
Maths topics are: 'Astro Physics', MegaHertz 
Maths topics are: 'Differential Equations', Cosine Series 
Integer value is 12 
Pi value is 3.14159 
Example for Any 
Topics 'solid physics', Hertz 

AnyObject 

The ‘AnyObject’ keyword is used for representing an instance of any class type. 

classSubjects { 
var physics: String 
   init(physics: String) { 
self.physics = physics 
   } 
} 
classChemistry: Subjects { 
var equations: String 
   init(physics: String, equations: String) { 
self.equations = equations 
super.init(physics: physics) 
   } 
} 
classMaths: Subjects { 
var formulae: String 
   init(physics: String, formulae: String) { 
self.formulae = formulae 
super.init(physics: physics) 
   } 
} 
let saprint: [AnyObject] = [Chemistry(physics: "solid physics", equations: "Hertz"), 
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"), 
Chemistry(physics: "Thermo physics", equations: "Decibels"), 
Maths(physics: "Astro Physics", formulae: "MegaHertz"), 
Maths(physics: "Differential Equations", formulae: "Cosine Series")] 
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz") 
print("Instance physics is: \(samplechem.physics)") 
print("Instance equation is: \(samplechem.equations)") 
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz") 
print("Instance physics is: \(samplemaths.physics)") 
print("Instance formulae is: \(samplemaths.formulae)") 
var chemCount = 0 
var mathsCount = 0 
for item in saprint { 
ifletprint = item as? Chemistry { 
print("Chemistry topics are: '\(print.physics)', \(print.equations)") 
   } elseiflet example = item as? Maths { 
print("Maths topics are: '\(example.physics)', \(example.formulae)") 
   } 
} 
var exampleany = [Any]() 
exampleany.append(12) 
exampleany.append(3.14159) 
exampleany.append("Example for Any") 
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz")) 
forprintin exampleany { 
switchprint { 
caselet someInt asInt: 
print("Integer value is \(someInt)") 
caselet someDouble asDoublewhere someDouble > 0: 
print("Pi value is \(someDouble)") 
caselet someString asString: 
print("\(someString)") 
caselet phy asChemistry: 
print("Topics '\(phy.physics)', \(phy.equations)") 
default: 
print("None") 
   } 
} 

The output for the above program would be 

Instance physics is: solid physics 
Instance equation is: Hertz 
Instance physics is: Fluid Dynamics 
Instance formulae is: Giga Hertz 
Chemistry topics are: 'solid physics', Hertz 
Maths topics are: 'Fluid Dynamics', Giga Hertz 
Chemistry topics are: 'Thermo physics', Decibels 
Maths topics are: 'Astro Physics', MegaHertz 
Maths topics are: 'Differential Equations', Cosine Series 
Integer value is 12 
Pi value is 3.14159 
Example for Any 
Topics 'solid physics', Hertz

Extensions 

Extensions in a layman’s language add to a class, structure, enumeration or type of protocol new functionality. This even includes the feasibility to extend types for which the original source code is not even available (called retroactive modeling). Extensions in Swift are exactly the same as categories in Objective-C.Swift extension within the  functionalities : 

  • Adding of the computed instance properties along with computed type properties. 
  • Defining both the instance methods and type methods. 
  • Providing a new i:e non existing initializers. 
  • Defines the subscripts. 
  • Define and even validates the new nested types. 
  • Making an existing type adhering  to a protocol. 

Syntax 

extension SomeType { 
   // new functionality can be added here 
} 

Existing type can also be added as a protocol standard with extensions and its syntax is similar to the classes or structures. 

extension SomeType: SomeProtocol, AnotherProtocol { 
   // protocol requirements is described here 
} 

Computed Properties 

With the help of extensions computed ‘instance’ and type properties can be extended. 

extension Int { 
varadd: Int {returnself + 100 } 
varsub: Int { returnself - 10 } 
var mul: Int { returnself * 10 } 
var div: Int { returnself / 5 } 
} 
let addition = 3.add 
print("Addition is \(addition)") 
let subtraction = 120.sub 
print("Subtraction is \(subtraction)") 
let multiplication = 39.mul 
print("Multiplication is \(multiplication)") 
let division = 55.div 
print("Division is \(division)") 
let mix = 30.add + 34.sub 
print("Mixed Type is \(mix)") 

The above program output would be 

Addition is 103 
Subtraction is 110 
Multiplication is 390 
Division is 11 
Mixed Type is 154 

Initializers 

Swift offers the flexibility of adding new initializers by extensions to an existing type. The user can add his own custom types to extend the defined types and also allow further initialization options. Only init() is supported by extensions. The deinit() are not supported by extensions. 

struct sum { 
var num1 = 100, num2 = 200 
} 
struct diff { 
var no1 = 200, no2 = 100 
} 
struct mult { 
var a = sum() 
var b = diff() 
} 
let calc = mult() 
print ("Inside mult block \(calc.a.num1, calc.a.num2)") 
print("Inside mult block \(calc.b.no1, calc.b.no2)") 
let memcalc = mult(a: sum(num1: 300, num2: 500),b: diff(no1: 300, no2: 100)) 
print("Inside mult block \(memcalc.a.num1, memcalc.a.num2)") 
print("Inside mult block \(memcalc.b.no1, memcalc.b.no2)") 
extension mult { 
   init(x: sum, y: diff) { 
let X = x.num1 + x.num2 
let Y = y.no1 + y.no2 
   } 
} 
let a = sum(num1: 100, num2: 200) 
print("Inside Sum Block:\( a.num1, a.num2)") 
let b = diff(no1: 200, no2: 100) 
print("Inside Diff Block: \(b.no1, b.no2)") 
The output for the above program would be 
Inside mult block (100, 200) 
Inside mult block (200, 100) 
Inside mult block (300, 500) 
Inside mult block (300, 100) 
Inside Sum Block:(100, 200) 
Inside Diff Block: (200, 100) 

Methods 

The extensions also help subclasses to add new instance methods and type methods. 

extension Int { 
   func topics(summation: () -> ()) { 
for _ in0..<self { 
         summation() 
      } 
   } 
} 
4.topics(summation: { 
print("Inside Extensions Block") 
}) 
3.topics(summation: { 
print("Inside Type Casting Block") 
}) 

The output for the above program would be 

Inside Extensions Block 
Inside Extensions Block 
Inside Extensions Block 
Inside Extensions Block 
Inside Type Casting Block 
Inside Type Casting Block 
Inside Type Casting Block

Mutating Instance Methods 

When declared as extensions, instance methods can also be mutated. 

Structures and enumeration methods that modify themselves or their properties must identify the instance method as mutating, as do methods from the original implementation. 

extension Double { 
   mutating func square() { 
let pi = 3.1415 
self = pi * self * self 
   } 
} 
varTrial1 = 3.3 
Trial1.square() 
print("Area of circle is: \(Trial1)") 
varTrial2 = 5.8 
Trial2.square() 
print("Area of circle is: \(Trial2)") 
varTrial3 = 120.3 
Trial3.square() 
print("Area of circle is: \(Trial3)")

Subscript & Nested type 

extension Int { 
   subscript(var multtable: Int) -> Int { 
var no1 = 1 
while multtable > 0 { 
         no1 *= 10 
         --multtable 
      } 
return (self / no1) % 10 
   } 
} 
print(12[0]) 
print(7869[1]) 
print(786543[2]) 

The extensions can help in extending nested types for class,structure and enumeration instance. 

extension Int { 
enum calc { 
caseadd 
casesub 
case mult 
case div 
case anything 
   } 
varprint: calc { 
switchself { 
case0: 
return .add 
case1: 
return .sub 
case2: 
return .mult 
case3: 
return .div 
default: 
return .anything 
      } 
   } 
} 
func result(numb: [Int]) { 
for i in numb { 
switch i.print { 
case .add: 
print(" 10 ") 
case .sub: 
print(" 20 ") 
case .mult: 
print(" 30 ") 
case .div: 
print(" 40 ") 
default: 
print(" 50 ") 
      } 
   } 
} 
result(numb: [0, 1, 2, 3, 4, 7]) 

Protocols 

A protocol defines the actual blueprint of any methods, its properties along with  other requirements which are perfectly suitable for a specific task or feature. Any class enumeration or structure can then take the protocol to ensure its actual execution. Any type of protocol complying with the requirements is said to comply with that protocol.You can extend the protocol to implement some of these needs and can also  implement additional functionality which conforms the types that  can be used.  Along with that it can even specify requirements that conform types that are a must for implementation. 

Syntax 
protocol SomeProtocol { 
   // protocol definition  
} 

Protocols are declared after names of class, structure or type of enumeration. It is also feasible to declare single and multiple protocols. When defining various protocols, they must be split up by commas. 

structSomeStructure: Protocol1, Protocol2 { 
// structure definition  
} 

If a protocol for superclass has to be defined, the name of the protocol should follow the name of  Super Class with commas. 

class SomeClass: SomeSuperclass, Protocol1, Protocol2 { 
   // class definition  
}

Property and Method Requirements 

A protocol is used to indicate a property of instance or instance of specific class type. It simply specifies the property of the type or instance alone, instead of whether it has been stored or computed property. It is also used to indicate if the property is 'gettable' or 'settable'. 

‘var' keyword declares property requirements as property variables. After their type declaration,{ get set} is used for declaring gettable and settable properties. Gettable is specified after a type declaration by{ get} property. 

protocol classa { 
var marks: Int { getset } 
var result: Bool { get } 
   func attendance() -> String 
   func markssecured() -> String 
} 
protocol classb: classa { 
var present: Bool { getset } 
var subject: String { getset } 
var stname: String { getset } 
} 
class classc: classb { 
var marks = 96 
let result = true 
var present = false 
var subject = "Swift Protocols" 
var stname = "Protocols" 
   func attendance() -> String { 
return"The \(stname) has secured 99% attendance" 
   } 
   func markssecured() -> String { 
return"\(stname) has scored \(marks)" 
   } 
} 
let studdet = classc() 
studdet.stname = "Swift" 
studdet.marks = 98 
studdet.markssecured() 
print(studdet.marks) 
print(studdet.result) 
print(studdet.present) 
print(studdet.subject) 
print(studdet.stname) 

The output for the above program would be  

98 
true 
false 
Swift  Protocols 
Swift 

Mutating Method Requirements 

protocol daysofaweek { 
   mutating func print() 
} 
enum days: daysofaweek { 
case sun, mon, tue, wed, thurs, fri, sat  
   mutating func print() { 
switchself { 
case sun: 
self = sun 
print("Sunday") 
case mon: 
self = mon 
print("Monday") 
case tue: 
self = tue 
print("Tuesday") 
case wed: 
self = wed 
print("Wednesday") 
case mon: 
self = thurs 
print("Thursday") 
case tue: 
self = fri 
print("Friday") 
case sat: 
self = sat 
print("Saturday") 
default: 
print("NO Such Day") 
      } 
   } 
} 
var res = days.wed 
res.print() 

Initializer Requirements 

Swift allows users to initialize protocols that conform like normal initializers to type compliance. 

Syntax 

protocol SomeProtocol { 
   init(someParameter: Int) 
} 
Example 
protocol tcpprotocol { 
   init(aprot: Int) 
} 

Class Implementations of Protocol Initializer Requirements 

To initialize a protocol,designated or convenience initializer allows the user to conform its standard by reserved ‘required’ keyword. 

lass SomeClass: SomeProtocol { 
   required init(someParameter: Int) { 
// initializer implementation statements 
   } 
} 
protocol tcpprotocol { 
   init(aprot: Int) 
} 
class tcpClass: tcpprotocol { 
   required init(aprot: Int) { 
   } 
} 

Conformity to the Protocol is guaranteed on all subclasses with a "required" modifier for explicit or inherited execution.When a subclass overrides its superclass initialization requirement, the' override' keyword is used. 

protocol tcpprotocol { 
   init(no1: Int) 
} 
class mainClass { 
var no1: Int// local storage 
   init(no1: Int) { 
self.no1 = no1  // initialization 
   } 
} 
class subClass: mainClass, tcpprotocol { 
var no2: Int 
   init(no1: Int, no2 : Int) { 
self.no2 = no2 
super.init(no1:no1) 
   } 
// Requires only one parameter for convenient method 
   required override convenience init(no1: Int) { 
self.init(no1:no1, no2:0) 
   } 
} 
let res = mainClass(no1: 20) 
letprint = subClass(no1: 30, no2: 50) 
print("res is: \(res.no1)") 
print("res is: \(print.no1)") 
print("res is: \(print.no2)")

Protocols as Types 

Protocols are used as types of functions , classes, methods, etc, instead of applying functionality in a protocol. 

There are numerous ways in which protocols can be applicable : 

  • The basic one includes the Function, method or can even initialize as a parameter or return type 
  • As a constant, variable or property 
  • Even as Arrays, dictionaries or other containers and as items. 
protocol Generator { 
   typealias members 
   func next() -> members? 
} 
var items = [10,20,30].generate() 
whilelet x = items.next() { 
print(x) 
} 
for lists in map([1,2,3], {i in i*5}) { 
print(lists) 
} 
print([100,200,300]) 
print(map([1,2,3], {i in i*10})) 

The output for the above program would be 

10 
20 
30 
5 
10 
15 
[100, 200, 300] 
[10, 20, 30]

 Adding Protocol Conformance with an Extension 

By using extensions, the existing type can be embraced and complied with by a fresh protocol. The existing type can be supplemented by extensions with new properties, methods, and subscripts. 

protocol AgeClasificationProtocol { 
var age: Int { get } 
   func agetype() -> String 
} 
classPerson { 
let firstname: String 
let lastname: String 
var age: Int 
   init(firstname: String, lastname: String) { 
self.firstname = firstname 
self.lastname = lastname 
self.age = 10 
   } 
} 
extension Person : AgeClasificationProtocol { 
   func fullname() -> String { 
var c: String 
      c = firstname + " " + lastname 
return c 
   } 
   func agetype() -> String { 
switch age { 
case0...2: 
return"Baby" 
case2...12: 
return"Child" 
case13...19: 
return"Teenager" 
caselet x where x > 65: 
return"Elderly" 
default: 
return"Normal" 
      } 
   } 
}

Protocol Inheritance 

Swift permits protocols to inherit properties that have been defined. It's comparable to class inheritance , but with several inheritance protocols separated by commas being listed. 

protocol classa { 
var no1:Int{getset} 
   func calc(sum:Int) 
} 
protocol result { 
   func print(target: classa) 
} 
class student2: result { 
   func print(target: classa){ 
      target.calc(sum:1) 
} 
} 
class classb: result { 
   func print(target: classa){ 
      target.calc(sum:5) 
} 
} 
class student: classa { 
var no1:Int=10 
   func calc(sum:Int){ 
      no1 -= sum 
print("Student attempted \(sum) times to pass") 
if no1 <=0{ 
print("Student is absent for exam") 
} 
} 
} 
classPlayer{ 
var stmark: result! 
   init(stmark: result){ 
self.stmark = stmark 
} 
   func print(target: classa){ 
      stmark.print(target: target) 
} 
} 
var marks =Player(stmark: student2()) 
var marksec = student() 
marks.print(target: marksec) 
marks.print(target: marksec) 
marks.print(target: marksec) 
marks.stmark = classb() 
marks.print(target: marksec) 
marks.print(target: marksec) 
marks.print(target: marksec) 

The above program output would be  

Student attempted 1 times to pass 
Student attempted 1 times to pass 
Student attempted 1 times to pass 
Student attempted 5 times to pass 
Student attempted 5 times to pass 
Student is absent for exam 
Student attempted 5 times to pass 
Student is absent for exam

 Class Only Protocols 

When protocols and class protocols are described, the user needs to add class first followed by the inheritance list of protocols. 

rotocol tcpprotocol { 
   init(no1: Int) 
} 
class mainClass { 
var no1: Int// local storage 
   init(no1: Int) { 
self.no1 = no1  // initialization 
   } 
} 
class subClass: mainClass, tcpprotocol { 
var no2: Int 
   init(no1: Int, no2 : Int) { 
self.no2 = no2 
super.init(no1:no1) 
   } 
// Requires only one parameter for convenient method 
   required override convenience init(no1: Int) { 
self.init(no1:no1, no2:0) 
   } 
} 
let res = mainClass(no1: 20) 
letprint = subClass(no1: 30, no2: 50) 
print("res is: \(res.no1)") 
print("res is: \(print.no1)") 
print("res is: \(print.no2)") 

Protocol composition 

The protocol composition can help multiple protocols to be called at once. 

Syntax 

protocol<SomeProtocol, AnotherProtocol> 
Example 
protocol stname { 
var name:String{get} 
} 
protocol stage { 
var age:Int{get} 
} 
structPerson: stname, stage { 
var name:String 
var age:Int 
} 
func print(celebrator: stname & stage){ 
print("\(celebrator.name) is \(celebrator.age) years old") 
} 
let studname =Person(name:"Priya", age:21) 
print(studname) 
let stud =Person(name:"Rehan", age:29) 
print(stud) 
let student =Person(name:"Roshan", age:19) 
print(student) 

Checking for Protocol Conformance

You can use the operators "is" and "as" defined in the type casting to verify protocol compliance and cast them into a particular protocol. The checking and casting on a protocol is identical to checking and casting to a type. 

  • The value of operator returns is visible as  true if an instance conforms to a protocol and returns false if it doesn’t. 
  • The as? version of the downcast operator always returns the optional value of the protocol’s type, and this value is actually nil if the instance doesn’t conform to that particular protocol. 
  • The as! version of the downcast operator even forces the downcast to the protocol type and activates a runtime error in the scenario where the downcast doesn’t succeed. 

importFoundation 

@objc protocol rectangle { 
var area: Double { get } 
} 
@objcclassCircle: rectangle { 
let pi = 3.1415927 
var radius: Double 
var area: Double { return pi * radius * radius } 
   init(radius: Double) { self.radius = radius } 
} 
@objcclass result: rectangle { 
var area: Double 
   init(area: Double) { self.area = area } 
} 
class sides { 
var rectsides: Int 
   init(rectsides: Int) { self.rectsides = rectsides } 
} 
let objects: [AnyObject] = [Circle(radius: 2.0),result(area:198),sides(rectsides: 4)] 
forobjectin objects { 
iflet objectWithArea = objectas? rectangle { 
print("Area is \(objectWithArea.area)") 
   } else { 
print("Rectangle area is not defined") 
   } 
} 

The output for the above program would be 

Area is 12.5663708 
Area is 198.0 
Rectangle area is not defined

Generic

Generic code allows you to write flexible, reusable functions and type, depending on criteria that you define, that can work with any type. You can write code which prevents duplication and clearly, abstractly expresses its purpose.

Generics are one of Swift's strongest characteristics and many Swift standard libraries are made from generic code. Swift's Array and Dictionary are generic collections, for instance. You can generate an array containing Int or an array containing String values or a set for any other type in Swift. Likewise, you can generate a dictionary to store any given type of values and there are no restrictions on what type.

func exchange(a: inout Int, b: inout Int) { 
let temp = a 
   a = b 
   b = temp 
} 
var numb1 = 100 
var numb2 = 200 
print("Before Swapping values are: \(numb1) and \(numb2)") 
exchange(a: &numb1, b: &numb2) 
print("After Swapping values are: \(numb1) and \(numb2)") 

The output for the above program would be 

Before Swapping values are: 100 and 200 
After Swapping values are: 200 and 100 
Generic Functions: Type Parameters 
Generic functions can be used to access any data type like 'Int' or 'String'. 
func exchange<T>(a: inout T, b: inout T) { 
let temp = a 
   a = b 
   b = temp 
} 
var numb1 = 100 
var numb2 = 200 
print("Before Swapping Int values are: \(numb1) and \(numb2)") 
exchange(a: &numb1, b: &numb2) 
print("After Swapping Int values are: \(numb1) and \(numb2)") 
var str1 = "Generics" 
var str2 = "Functions" 
print("Before Swapping String values are: \(str1) and \(str2)") 
exchange(a: &str1, b: &str2) 
print("After Swapping String values are: \(str1) and \(str2)") 

The output for the above program would be  

Before Swapping Int values are: 100 and 200 
After Swapping Int values are: 200 and 100 
Before Swapping String values are: Generics and Functions 
After Swapping String values are: Functions and Generics 

The exchange() function is used to exchange values outlined above, and < T > is used as a parameter sort. The exchange() function is called first to return the value of' Int' and then the second call to the exchange() function gives the value of' String.' Inside the angle brackets, separated by commas, several parameter types can be included. 

The user-specified parameters of the type are named to understand what type of parameter it holds. As a generic parameter type name, Swift offers < T>. However, parameters such as Arrays and Dictionaries can be used to define that they are of the' Dictionary' type. 

struct TOS<T> { 
var items = [T]() 
   mutating func push(item: T) { 
      items.append(item) 
   } 
   mutating func pop() -> T { 
return items.removeLast() 
   } 
} 
var tos = TOS<String>() 
tos.push(item: "Swift ") 
print(tos.items) 
tos.push(item: "Generics") 
print(tos.items) 
tos.push(item: "Type Parameters") 
print(tos.items) 
tos.push(item: "Naming Type Parameters") 
print(tos.items) 
let deletetos = tos.pop() 

The output for the above program  would be  

[Swift ] 
[Swift , Generics] 
[Swift , Generics, Type Parameters] 
[Swift , Generics, Type Parameters, Naming Type Parameters] 

Extending a Generic Type 

Extending the stack property to know the top of the item is included with 'extension' keyword. 

struct TOS<T> { 
var items = [T]() 
   mutating func push(item: T) { 
      items.append(item) 
   } 
   mutating func pop() -> T { 
return items.removeLast() 
   } 
} 
var tos = TOS<String>() 
tos.push(item: "Swift ") 
print(tos.items) 
tos.push(item: "Generics") 
print(tos.items) 
tos.push(item: "Type Parameters") 
print(tos.items) 
tos.push(item: "Naming Type Parameters") 
print(tos.items) 
extension TOS { 
var first: T? { 
return items.isEmpty ? nil : items[items.count - 1] 
   } 
} 
iflet first = tos.first { 
print("The top item on the stack is \(first).") 
} 

The output for the above program would be 

["Swift "] 
["Swift ", "Generics"] 
["Swift ", "Generics", "Type Parameters"] 
["Swift ", "Generics", "Type Parameters", "Naming Type Parameters"] 
The top item on the stack is Naming Type Parameters. 

Type Constraints 

Specifically,' type constraints’' may allow the specified type parameter to be inherited from a certain class, or the protocol conformity standard to be ensured. 

func exchange<T>(a: inout T, b: inout T) { 
let temp = a 
   a = b 
   b = temp 
} 
var numb1 = 100 
var numb2 = 200 
print("Before Swapping Int values are: \(numb1) and \(numb2)") 
exchange(a: &numb1, b: &numb2) 
print("After Swapping Int values are: \(numb1) and \(numb2)") 
var str1 = "Generics" 
var str2 = "Functions" 
print("Before Swapping String values are: \(str1) and \(str2)") 
exchange(a: &str1, b: &str2) 
print("After Swapping String values are: \(str1) and \(str2)") 

The output for the above program would be 

Before Swapping Int values are: 100 and 200 
After Swapping Int values are: 200 and 100 
Before Swapping String values are: Generics and Functions 
After Swapping String values are: Functions and Generics

Associated Types 

In the protocol definition, Swift allows associated types to be declared by the' associatedtype' keyword. 

protocol Container { 
   associatedtype ItemType 
   mutating func append(item: ItemType) 
var count: Int { get } 
   subscript(i: Int) -> ItemType { get } 
} 
struct TOS<T>: Container { 
// original Stack<T> implementation 
var items = [T]() 
   mutating func push(item: T) { 
      items.append(item) 
   } 
   mutating func pop() -> T { 
return items.removeLast() 
   } 
// conformance to the Container protocol 
   mutating func append(item: T) { 
self.push(item: item) 
   } 
var count: Int { 
return items.count 
   } 
   subscript(i: Int) -> T { 
return items[i] 
   } 
} 
var tos = TOS<String>() 
tos.push(item: "Swift 4") 
print(tos.items) 
tos.push(item: "Generics") 
print(tos.items) 
tos.push(item: "Type Parameters") 
print(tos.items) 
tos.push(item: "Naming Type Parameters") 
print(tos.items) 

The output for the above program would be

Access Control:

Access control limits access by other source files and modules to parts of your code from the code. This feature assists the user to hide the implementation details of the user code, and to specify a particular interface through which that code can be accessed and easily used by the end users. 

In addition to offering different levels of control of access, Swift reduces the requirement for explicit levels of access control by providing standard access levels for typical scenarios. 

Module and abstraction are done through access control to restrict access to code blocks. According to their properties, methods, initializers and subscriptions, access to classes, structures and enumerations can be achieved through access control procedures. 

Access control is applicable to properties, types and functions can be referred to as 'entities'. Constants, variables and functions are restricted in a protocol and allowed access as global or local by way of access control. 

Modules and source files are the basis of the Access Control Model. 

The module is described as a single distribution unit of code and can be exported using an 'import' keyword. 

A single source file with multiple types and features in a module is defined as the source file. 

Three different types of access provided by Swift language  are: 

Public, Internal and Private 

  1. Public: It is considered as the least restrictive access.  This type of access enables an entity to be accessed outside defining module.          
  2. Internal: It enables the use of entities within any source file of their module, but not outside that module in any source file. 
  3. Private: It is classified as the most restrictive access. This type of access hides the implementation details of defining  module. 

Syntax: 

public class SomePublicClass {} 
internal class SomeInternalClass {} 
private class SomePrivateClass {} 
public var somePublicVariable = 0 
internal let someInternalConstant = 0 
private func somePrivateFunction() {}

Access control for function types: 

Some functions may even have their arguments being declared within the function without any return values. Such programs declare a and b as arguments to the sum() function. Within the function itself the values for the arguments a and b are fed by invoking the function call sum() and its values are automatically printed; thereby completely eliminating the return values. Inorder to make the function's return type as private, the end user declares the function’s overall access level with a private modifier. 

Live demo for the same would be: 

private func sum(a: Int, b: Int) { 
let a = a + b 
let b = a - b 
print(a, b) 
} 
sum(a: 20, b: 10) 
sum(a: 40, b: 10) 
sum(a: 24, b: 6) 

The output achieved in this case is  

30 20 
50 40 
30 24 

Access Control for Enumeration Types: 

Live Demo 
publicenumStudent { 
caseName(String) 
caseMark(Int,Int,Int) 
} 
var studDetails = Student.Name("Swift 4") 
var studMarks = Student.Mark(98,97,95) 
switch studMarks { 
case .Name(let studName): 
print("Student name is: \(studName).") 
case .Mark(letMark1, letMark2, letMark3): 
print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).") 
} 

While running this program with the playground we achieve the following output: 

Student Marks are: 98,97,95 

For individual cases of an enumeration, the listing in Swift 4 automatically receives the same level of access. 

Consider accessing the name and trademarks of students in three subjects, for example. Enumerated names are declared as students and members of the enum class are names of a data type string, mark 2, and mark3 of an Integer data type. 

They have entered either the name of the student or the marks. Now, if that case block is carried out, the switch case will print out the name of the student. If both conditions fail, the default block will be executed.

Access control of Subclasses: 

Swift 4 enables the user to subclass any class accessible in the existing access framework. 

A subclass cannot be greater than its superclass access level. A public subclass of an internal superclass is limited for the user. 

publicclass cricket { 
internal func printIt() { 
print("Welcome to Swift 4 Super Class") 
   } 
} 
internalclass tennis: cricket { 
overrideinternal func printIt() { 
print("Welcome to Swift 4 Sub Class") 
   } 
} 
let cricinstance = cricket() 
cricinstance.printIt() 
let tennisinstance = tennis() 
tennisinstance.printIt() 

On running the above program with the playground, the following output can be achieved: 

Welcome to Swift Super Class 
Welcome to Swift Sub Class

Access Control for Constants, variables, properties, and subscripts: 

Swift 4 is not defined as the public constant, variable, or characteristic other than the type. A public property with a personal form is not valid to be documented. More so, a subscript cannot be more public in comparison to its index or return type. 

If a constant, variable, property or subscript uses a private form, it must also be labeled privately as a constant, variable, property or subscription 

private var privateInstance = SomePrivateClass() 

Getters and Setters: 

The same access levels are automatically received by getters and setters of constant, variable, properties and subscript to which they actually belong to. 

class Samplepgm { 
var counter: Int = 0{ 
      willSet(newTotal) { 
print("Total Counter is: \(newTotal)") 
      } 
      didSet { 
if counter > oldValue { 
print("Newly Added Counter \(counter - oldValue)") 
         } 
      } 
   } 
} 
letNewCounter = Samplepgm() 
NewCounter.counter = 100 
NewCounter.counter = 800 

The output of the above program is shown below: 

Total Counter is: 100 
Newly Added Counter 100 
Total Counter is: 800 
Newly Added Counter 700

Access Control for Initializers and Default Initializers

Custom initializers can actually be assigned the access less than or equal to the initialized type.The required initializer must have the same amount of access as its class. The types of parameters of an initializer cannot be more private than the access level of the initializer itself. 

For declaration of each and every subclass of the initialize,the 'required' keyword needs to be pre-defined prior the init() function. 

class classA { 
   required init() { 
let a = 10 
print(a) 
   } 
} 
class classB: classA { 
   required init() { 
let b = 30 
print(b) 
   } 
} 
let res = classA() 
letprint = classB() 

Following outputs are obtained by running the above program: 

10 
30 
10 

A default initializer has the same level of access as its initialised type, unless that type is publicly defined.If initializing by default is public, it is internally considered. If the user needs to have a public type initialized in another module with a no-argument initializer, it provides exclusively a public no-argument initializer as part of the type's definition.

Access control for Protocols:  

The same levels of access to each other must be stated when defining a new protocol to inherit functions from the existing prototype.The Swift 4 access control will not enable users inherent in an 'internal' protocol to define a 'public' protocol. 

public protocol tcpprotocol { 
   init(no1: Int) 
} 
publicclass mainClass { 
var no1: Int// local storage 
   init(no1: Int) { 
self.no1 = no1 // initialization 
   } 
} 
class subClass: mainClass, tcpprotocol { 
var no2: Int 
   init(no1: Int, no2 : Int) { 
self.no2 = no2 
super.init(no1:no1) 
   } 
// Requires only one parameter for convenient method 
   required override convenience init(no1: Int) { 
self.init(no1:no1, no2:0) 
   } 
} 
let res = mainClass(no1:20) 
let print = subClass(no1:30, no2:50) 
print("res is: \(res.no1)") 
print("res is: \(print.no1)") 
print("res is: \(print.no2)") 

While running the program, the following output is being achieved: 

res is: 20 
res is: 30 
res is: 50

 Access Control for Extensions:

Swift 4 does not entertain the end users to facilitate an explicit access level modifier for an extension when the user uses that particular extension to add protocol conformance. The default access level in case of every single protocol requirement actually does the implementation within the extension and  is provided with its very own protocol access level.

Access Level for Generics:

In case of Generics users are allowed to specify minimum access levels to access the type constraints along with its type parameters.

public struct TOS<T> { 
var items = [T]() 
   mutating func push(item: T) { 
      items.append(item) 
   } 
   mutating func pop() -> T { 
return items.removeLast() 
   } 
} 
var tos = TOS<String>() 
tos.push(item: "Swift 4") 
print(tos.items) 
tos.push(item: "Generics") 
print(tos.items) 
tos.push(item: "Type Parameters") 
print(tos.items) 
tos.push(item: "Naming Type Parameters") 
print(tos.items) 
let deletetos = tos.pop() 

The following results are obtained when the program is being run: 

[Swift 4] 
[Swift 4, Generics] 
[Swift 4, Generics, Type Parameters] 
[Swift 4, Generics, Type Parameters, Naming Type Parameters] 

Access Control for Type Aliases:

The user can readily define type aliases to treat the unique access control types, whereas the same or different access levels can be easily identified by the user. In scenarios wherein the type alias is 'private' its associated members can be declared as 'private, internal of public type', and in the situations wherein the type alias is public the members cannot be an alias as an 'internal' or 'private' name. 

Any type aliases defined are regarded as distinct types for the exclusive purposes of access control. A type alias can even have an access level less than or equal to the access level of the type its aliases have in original. For example, a private type alias can actually alias a private, internal, or public type in contrary to which  a public type alias cannot alias an internal or private type. 

public protocol Container { 
   associatedtype ItemType 
   mutating func append(item: ItemType) 
var count: Int { get } 
   subscript(i: Int) -> ItemType { get } 
} 
structStack<T>: Container { 
// original Stack<T> implementation 
var items = [T]() 
   mutating func push(item: T) { 
      items.append(item) 
   } 
   mutating func pop() -> T { 
return items.removeLast() 
   } 
// conformance to the Container protocol 
   mutating func append(item: T) { 
self.push(item: item) 
   } 
var count: Int { 
return items.count 
   } 
   subscript(i: Int) -> T { 
return items[i] 
   } 
} 
func allItemsMatch< 
   C1: Container, C2: Container 
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable> 
   (someContainer: C1, anotherContainer: C2) -> Bool { 
// check that both containers contain the same number of items 
if someContainer.count != anotherContainer.count { 
returnfalse 
   } 
// check each pair of items to see if they are equivalent 
for i in0..<someContainer.count { 
if someContainer[i] != anotherContainer[i] { 
returnfalse 
      } 
   } 
// all items match, so return true 
returntrue 
} 
var tos = Stack<String>() 
tos.push(item: "Swift 4") 
print(tos.items) 
tos.push(item: "Generics") 
print(tos.items) 
tos.push(item: "Where Clause") 
print(tos.items) 
var eos = ["Swift 4", "Generics", "Where Clause"] 
print(eos) 

The following output is being achieved while the above program is being run: 

[Swift 4] 
[Swift 4, Generics] 
[Swift 4, Generics, Where Clause] 
[Swift 4, Generics, Where Clause] 

Swift Encoding and Decoding: 

Swift 4 introduces the new Codable protocol, which allows you to serialize and remove customized data types without any special code – and without worrying about losing your value types. 

struct Language: Codable { 
var name: String 
var version: Int 
} 
let swift = Language(name: "Swift", version: 4) 
let java = Language(name: "java", version: 8) 
let R = Language(name: "R", version: 3 
let encoder =JSONEncoder() 
iflet encoded =try? encoder.encode(java){ 
//Perform some operations on this value. 
} 
let decoder =JSONDecoder() 
iflet decoded =try? decoder.decode(Language.self,from: encoded){ 
//Perform some operations on this value. 
} 

Summary:

This module covered all other details related to ARC ,optional chaining ,type casting ,extensions ,protocols and generics. We have also got fair understanding of access control with help of this module.

Leave a Reply

Your email address will not be published. Required fields are marked *

Suggested Tutorials

R Programming Tutorial

R Programming

C# Tutorial

C# is an object-oriented programming developed by Microsoft that uses the .Net Framework. It utilizes the Common Language Interface (CLI) that describes the executable code as well as the runtime environment. C# can be used for various applications such as web applications, distributed applications, database applications, window applications etc.For greater understanding of this tutorial, a basic knowledge of object-oriented languages such as C++, Java etc. would be beneficial.
C# Tutorial

C# is an object-oriented programming developed by Microsoft that uses ...

Read More

Python Tutorial

Python Tutorial