In this instalment we will review Classes and Structures

Classes and structure

In swift classes and structure are almost similar, structs are copied when passed around and don't use reference counting

Int, String, Array, Dictionary all are implemented as Structures behind the scene, hence they are all Value Types

Defining

class ClassName {
    //Methods and Vars
}

struct StructName {
    //Methods and Vars
}

//Instantiation
var c = ClassName()
var s = StructName()

Identity Operators

Since Classes are reference type it could be useful to check if two variables hold the same class instance

c1 === c2 //Identical
c1 !== c2 //Not identical

Properties

Stored properties

Normal properties of a class or struct denoted by var or let

Lazy properties

Are a special type of properties that are only calculated once accessed.

class DataManager {
    @lazy var importer = DataImporter() //Create new instance of a class    
}

//When accessed the DataImporter is calculated
dm.importer
Computed properties

A type of property that do not store the value, but provide a way to compute it

class TestClass {
  var prop: String {
  get {
    return "String"
  }

  set {
    //Store it
    self.prop = newValue
  }
  }
}

If the computed property specify only set, it will become a read only property, or by only having 1 block

class TestClass {
  var prop: String { //readonly
    return "String"
  }
}
Property Observers

Property observers observe and respond to changes in a property’s value. Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value

Observers work for instance and local variables
willSet is called before value is set and didSet after

 var prop: Int = 0 {
 willSet { /* access new with newValue */ } //Called before setting
 didSet { /*access old by oldValue */ } //Called after setting 
}

Also note that changing the value inside an observer does not call the observers back

Type Properties

Type properties are static properties that only have 1 value per type per execution
These are static for structs and class for class

//Class can only have computed type property
class TestClass {
  class var c: String {
    get {
      return "Test"
    }
  }
}
//Access
TestClass.c

//Structs can have computed and stored
struct TestStruct {
  static var c1: String {
    get {
      return "Test"
  }
  }

  static var c2 = "Test"
}
//Access
TestStruct.c1

Methods

Instance Methods

Are functions that belong to an instance

Mutating Methods

Functions of a struct cannot modify the struct properties, you can opt into this by placing mutating before function declaration
A mutating method can even reassign self

struct TestStruct {
  var x = 1
  mutating func xChanger () {     
    self.x = 2
    //self = new stuff
  }
}
Type Methods

Are method called on the type itself you specify a type method by adding static before func for structs and class for method

Subscripts

Subscripts are shortcuts to access and modify the members of a class

//Examples
array[index]
dictionary[key]
Subscript Syntax

You define a subscript using subscript keyword, subscripts can have get and set

Subscripts take a multiple values in and return a value

 subscript(index: Int) -> Int {
   get { }
   set { /* newValue */ }
 }
Final classes

You can prevent a class or method from being overridden with override by adding @final before it

Initialisation

By the end of any init method all the store properties (which are non optional) of a class or struct must be set

class Base {
  var var1: Int
  init () {
    //By the end of init var1 MUST be set
    var1 = 10
  }
}

You can also fill in any constant properties value within init method

Convenience initialiser are written with convenience keyword before init

class Base {
  var var1: Int
  convenience init () {
    //By the end of init var1 MUST be set
    var1 = 10
  }
}
Lazy initialise a property with a closure

You can defer the initialisation of a property to an execution of closure, check example

class Sub : Base {
  var var2: Int = {
    return 4
  }()
}
Deinitialization

Called before class is deallocated

 deinit {
 //Clean stuff here    
 }
Strong and Weak

weak are created by placing weak before var declaration, since weak could have no value they are always optional ?
unowned are created by adding unowned before a var declaration, unowned must always have a value and hence are non optional

Strong retain cycle in closures

closures could cause a strong retain cycle when it access properties from self.

This can be solved using capture lists.

//Strong Cycle
class Test {
  var var1 = 5
  @lazy var closure: () -> Int = {
    return self.var1
  }

  //Solution
  @lazy var closure: () -> Int = {
    [unowned self] in //capture self as unowned
    return self.var1
  }
}