Tuesday, May 31, 2016

Swift 2.2 Brief Introduction for Experienced Programmer - Part 6 - Protocols & Extension

Protocol and Extension 

Protocol 

We can use protocol to provide a standard interface for other developer to adopt its API. Protocol also allow the flexibility for protocol adopter to implement details in their own way. We can introduce a protocol such as printing protocol and let any class instances, structures or any data type to adopt the features. While defining protocol, we standardized the input and output but we leave the implementation details to the adopter.

We can include computed properties and/or function in a protocol. For computed properties, we must define if the properties are settable and/or gettable. For function, we just need to define the function name and perimeters.

We use protocol to create and define a protocol
An example

class StudentA {
    var lastName: String
    var firstName: String
    var studentID: String
    var address: String
    var contact: Int
    
    init(lastName: String, firstName: String, studentID: String, address: String, contact: Int) {
        self.lastName = lastName
        self.firstName = firstName
        self.studentID = studentID
        self.address = address
        self.contact = contact
    }
}

  • Consider the example above, if we need to add functionality to display student record on the screen, we need to add the functionality using method, however, in this case we can create a protocol so that any other class can also make use of this feature..

protocol printToScreen {
    func printScreen()
}

class StudentB: printToScreen {
    var lastName: String
    var firstName: String
    var studentID: String
    var address: String
    var contact: Int
    
    init(lastName: String, firstName: String, studentID: String, address: String, contact: Int) {
        self.lastName = lastName
        self.firstName = firstName
        self.studentID = studentID
        self.address = address
        self.contact = contact
    }
    
    func printScreen() {
        print("Name: \(lastName), \(firstName)")
        print("Student ID: \(studentID)")
        print("Address: \(address)")
        print("Contact: \(contact)")
    }
}

let student1 = StudentB(lastName: "Hawk", firstName: "Howard", studentID: "A122334", address: "sample address", contact: 256558745)
student1.printScreen()

  • We can also create a protocol that create a fullname

protocol FullName {
    var studentFullName: String {get}
}

class Student: printToScreen, FullName {
    var lastName: String
    var firstName: String
    var studentID: String
    var address: String
    var contact: Int
    
    init(lastName: String, firstName: String, studentID: String, address: String, contact: Int) {
        self.lastName = lastName
        self.firstName = firstName
        self.studentID = studentID
        self.address = address
        self.contact = contact
    }
    
    var studentFullName: String {
        get {
            return self.firstName+" "+self.lastName
        }
    }
    
    func printScreen() {
        print("Name: \(studentFullName)")
        print("Student ID: \(studentID)")
        print("Address: \(address)")
        print("Contact: \(contact)")
    }
}

let student2 = Student(lastName: "Hopkin", firstName: "Tom", studentID: "A122164", address: "sample address for Tom", contact: 2579654785)
student2.printScreen()
student2.studentFullName

  • A protocol can contain properties and function. Please note that properties in protocol is similar to computed properties, you need to specify set and/or get for each properties. For function, we need to specify the arguments' data type and return data type.

protocol SampleProtocol {
    var capitalTextGet: String {get}
    var someNumberGetSet: Int {get set}
    
    mutating func displayText()
    func time2Number(numberEntry: Int) -> Int
}

class SomeClass1:SampleProtocol {
    
    var somePropertyNumber:Int
    var somePropertyText: String
    var capitalTextGet: String {
        get {
            return self.somePropertyText.uppercaseString
        }
    }
    var someNumberGetSet: Int
    
    init(enterText: String, number: Int) {
        self.somePropertyNumber = number
        self.somePropertyText = enterText
        self.someNumberGetSet = number * number
    }
    
    func displayText() {
        print("This is property \(self.somePropertyText) and this is \(self.capitalTextGet)")
    }
    
    func time2Number(numberEntry: Int) -> Int {
        return numberEntry * 2
    }
}

let mySampleObj1 = SomeClass1(enterText: "bmw", number: 88)
mySampleObj1.somePropertyNumber
mySampleObj1.somePropertyText
mySampleObj1.capitalTextGet
mySampleObj1.someNumberGetSet
mySampleObj1.displayText()
mySampleObj1.time2Number(66)

  • If we assign the object to another variable with protocol specified,  the assigned object will only adopt the protocol part and will not allow access to the class properties or function

let sampleObj1a: SampleProtocol = mySampleObj1
sampleObj1a.capitalTextGet
sampleObj1a.someNumberGetSet
sampleObj1a.time2Number(66)
//sampleObj1a.displayText()  error as the instance can use protocol but not the base class

  • We can use protocol for classes, structure and enumerations

struct SampleStruct: SampleProtocol {
    
    let myStructProperty = 2018
    var capitalTextGet: String
    var someNumberGetSet: Int
    
    init(text: String, number: Int) {
        self.capitalTextGet = text
        self.someNumberGetSet = number
    }
    
    mutating func displayText() {
        print("This is a struct")
        self.capitalTextGet = "This is a struct with mutating method"
    }
    
    func time2Number(numberEntry: Int) -> Int {
        return numberEntry * numberEntry
    }
    
}

var mySampleStruct1 = SampleStruct(text: "This is a struct", number: 1024)
mySampleStruct1.myStructProperty
mySampleStruct1.capitalTextGet
mySampleStruct1.someNumberGetSet
mySampleStruct1.displayText()
mySampleStruct1.time2Number(8)

  • Please also note that we need to add a keyword mutating to functions that modifies the structure itself. This only applies to structures only. 
  • In addition we need to add mutating to the function during protocol definition. 
  • If we plan for developers to adopt the protocol in structures and the functions involved in modifying the properties. It is better to add the mutating keyword in front of the affected function. 
 Creating enumeration with the adoption of protocol

enum SampleNum: SampleProtocol {
    case Element1(String)
    case Element2(Int)
    
    var capitalTextGet: String {
        get {
            return "enums"
        }
    }
    var someNumberGetSet: Int {
        get {
            return 10
        }
        set {
            10
        }
    }
    
    func displayText() {
        print("This is enum")
    }
    
    func time2Number(numberEntry: Int) -> Int {
        return numberEntry * 2
    }
}

var myNum = SampleNum.Element1("Enum Test")
myNum.capitalTextGet
myNum.someNumberGetSet
myNum.displayText()
myNum.time2Number(5)

  • Protocol is best used for interface that can be used across class instances, structures and enumerations. 
  • It can also be used for methods in a class that was overridden most often. 
  • By using protocol instead of method, we reduce the weight of a class and at the same time allows flexibility in the implementation of such function.


Extension

  • We can use extension to add functionality of an existing class. 
  • Extensions do not allows stored properties but allows computed properties and additional functions.  

extension SomeClass1 {
    var extraNumber: Int {
        return somePropertyNumber * 3
    }
    
    func notes(notes: String) {
        print(notes)
    }
}

let mySampleObj2 = SomeClass1(enterText: "batman", number: 88)
mySampleObj2.somePropertyText
mySampleObj2.capitalTextGet
mySampleObj2.someNumberGetSet
mySampleObj2.displayText()
mySampleObj2.time2Number(66)
mySampleObj2.extraNumber
mySampleObj2.notes("Some notes for extension")

  • We can also create an extension that adopts a protocol

class SomeClass2 {
    var notes: String
    var number2: Int
    
    init(notes: String, number2: Int) {
        self.notes = notes
        self.number2 = number2
    }
}

extension SomeClass2: SampleProtocol {

    var capitalTextGet : String {
        return notes
    }
    
    var someNumberGetSet: Int {
        get {
            return number2 * 10
        }
        set {
            number2 = newValue
        }
    }
    
    func displayText() {
        print(notes)
    }
    
    func time2Number(numberEntry: Int) -> Int {
        return numberEntry * 5
    }
    
}

  • If we use protocol adoption in an extension, we must make sure that all properties in the protocol must be setup as computed properties with get and set clearly defined. 

A collection of playgrounds file for this tutorial can be found at https://github.com/SwiftiCode/Swift-Brief-Note-Playground

*** End ***

Sunday, May 29, 2016

Swift 2.2 Brief Introduction for Experienced Programmer - Part 5 - Structures & Enumeration

Enumerations and Structures 

Enumerations 

  • To create enumerations, use keyword `enum`.   In Swift, we can associate methods in enumerations
enum Direction1 {
    case North, South, East, West
}
Direction1.South
Direction1.North.hashValue
Direction1.West.hashValue

let east = Direction1.East
east.hashValue

  • By default, Swift starts its enum hash value from 0. 
  • We can define the enum as above and use the elements above without considering the hash value if the underlying number is not important 
  • However, in cases where underlying number is important, we need to set the starting number.
  • But lets look at the enumeration without setting any starting number.
enum Month1 {
    case Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
}

Month1.Jan.hashValue
Month1.Jul.hashValue

  • The example above shows that the hash value for months are not exactly right. 
  • If we need to utilize the underlying number, Swift allows us to reset the starting number. 
  • But first we need to define the raw data type first before we can assign start number.
enum Month2: Int {
    case Jan = 1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
}

Month2.Apr
Month2.Jan.hashValue
Month2.Jan.rawValue

  • In the above example, since we define Int as its underlying raw value data type, we can set the raw value as per our preference. The hash value remain the same. 
  • We can also define the raw value other than Int.
enum Metric: String {
    case metric = "y", english = "n"
}

Metric.metric.rawValue
Metric.metric.hashValue
Metric.english.rawValue
Metric.english.hashValue

let userInput1 = 130.0
let userInputMetric = "n"
if userInputMetric == Metric.english.rawValue {
    print("Your weight which is \(userInput1) pounds is \(userInput1 * 0.453592) kg.")
}

  • We can also create enum base on yes and no answer
enum GotMetric {
    case no, yes
}

let userInput2 = 250.0
let userInputMetric2 = GotMetric.no
if userInputMetric2 == GotMetric.no {
    print("Your weight which is \(userInput2) pounds is \(userInput2 * 0.453592) kg.")
}

  • We can also add function in the enumeration. 
  • In the following example, we will be using the months example and include a function that will return number of days in a month. We ignore leap year in this example.
enum Months: Int {
    case Jan = 1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
    func days() -> Int {
        switch self {
        case .Jan, .Mar, .May, .Jul, .Aug, .Oct, .Dec:
            return 31
        case .Apr, .Jun, .Sep, .Nov:
            return 30
        case .Feb:
            return 28
        }
    }
}

Months.Jul
Months.Jul.rawValue
Months.Jul.days()
Months.Nov.days()
Months.Feb.days()

  • We can use init?(rawValue:) to create an instance from raw value 
  • Using the Months example above
let sep = Months.init(rawValue: 9)
sep

  • Another example without meaningful raw value
enum Direction {
    case North, South, East, West
    func displayHeading() -> String {
        switch self {
        case .North:
            return "Heading North"
        case .South:
            return "Heading South"
        case .East:
            return "Heading East"
        case .West:
            return "Heading West"
        }
    }
}

Direction.East.displayHeading()

  • For enumeration, we can create an enumeration without raw value and we associated different value while creating the instance.
enum Metric2 {
    case metric(String)
    case english(String)
}


var myMetric = Metric2.metric("yes")
myMetric
myMetric = Metric2.english("english")
myMetric

var myMetric2 = Metric2.metric("aye")
myMetric2 = Metric2.english("pounds")
myMetric

  • The above example is different from the example below where raw value is predefined. When you set raw value, all different instances will be the same whereas associated value can be different.
enum Metric3: String {
    case metric = "y", english = "n"
}

var myMetric3 = Metric3.metric
myMetric3.rawValue

myMetric3 = Metric3.english
myMetric3.rawValue

var myMetric4 = Metric3.metric
myMetric4.rawValue

Structure 

  • In Swift, structures not only contain variables or constant, it can also include function. 
  • We can also initialize the structures and include computed properties. 
  • The difference between structures and class instances is that structures are copied when assigning to a instance variable whereas instances from objects are referenced.
struct Circle {
    
    var radius: Double
    let myPi = 3.1415
    
    init(radius: Double) {
        self.radius = radius
    }
    
    var area: Double {
        return radius * radius * myPi
    }
    
    var circumference: Double {
        return 2 * radius * myPi
    }
    
    func display() -> String {
        return "The area and circumference of a radius \(radius) is \(area) and \(circumference) respectively."
    }
    
}

let s1 = Circle(radius: 25.0)
s1.area
s1.circumference
s1.radius
s1.display()

var s2 = s1
s2.radius = 30
s2.radius
s2.area
s2.circumference
s2.display()

s1.radius
s1.area
s1.circumference
s1.display()
  • In the above example, when you assign s2 with s1, the entire structure is copied to s2.
  • If you declared s2 as constant, it will be an exact copy of s1. 
  • If you declared s2 as variable you can modified s2 and the results of s2 and s1 will be different. 

A collection of playgrounds file for this tutorial can be found at https://github.com/SwiftiCode/Swift-Brief-Note-Playground

*** End ***

Sunday, May 22, 2016

Swift 2.2 Brief Introduction for Experienced Programmer - Part 4 - Classes

Objects and Classes 

Create Classes 

The syntax to create class is to use the keyword class follow by class name. A property declaration is the same as declaring constant and variables. Declaration of a method is the same way as declaring function

class Hi
{
    var hiName:String = "Name"
    func displayMessage()
    {
        print("Hi \(hiName), how are you?")
    }
}

  • To create an instance of a class, we use className(). 
  • We can assign instance like constant or variable. 
  • To read or write the property of a class, we use period (.)

              objectName.propertyName //read
              objectName.propertyName = newValue //write

  • To call the method of a class we use period (.) follow by parentheses ()      

               objectName.methodA()
var hiObj1 = Hi()
hiObj1.hiName = "Thomas"
hiObj1.hiName
hiObj1.displayMessage()

class Circle1 {
    
    let myPi = 3.1415
    var myRadius = 0.0
    
    func circumference() -> Double {
        return 2 * myRadius * myPi
    }
}

let objCircle1 = Circle1()
objCircle1.myRadius
objCircle1.myRadius = 25
objCircle1.circumference()

Initialization 

When creating an instance/object from a class, the properties must be initialized. This means that all properties in a class must be initialized, or all properties must have an assigned value. We accomplish such initialization by 2 methods:

  • The first method is to assigned a value immediately during declaration 
  • Another method is to assigned value by taking input from user using init() 
We use self.propertyName to refer to the current instance.

  • The following example require user to initialized the instance first before we can use the object.

class Circle2 {
    
    let myPi = 3.1415
    var myRadius:Double
    
    init(myRadius: Double) {
        self.myRadius = myRadius
    }
    
    func circumference() -> Double {
        return 2 * myRadius * myPi
    }
    
    func area() -> Double {
        return myRadius * myRadius * myPi
    }
}

let objCircle2 = Circle2(myRadius: 25)
objCircle2.myRadius
objCircle2.circumference()
objCircle2.area()

Sub Class

  • To create a subclass, we use the same class syntax follow by a colon and the name of superclass 
  • For initialization, we need to initialize the current properties before we can initialize the properties in the superclass.

class Cylinder:Circle2 {
    
    var height: Double
    
    init(height: Double, myRadius: Double) {
        self.height = height
        super.init(myRadius: myRadius)
    }
    
    func volume() -> Double {
        return self.area() * height
    }
}

let objCylinder1 = Cylinder(height: 10, myRadius: 25)
objCylinder1.myRadius
objCylinder1.circumference()
objCylinder1.area()
objCylinder1.height
objCylinder1.volume()

  • We can replace a method from the superclass by using the keyboard override

class HalfCylinder:Circle2 {
    
    var height: Double
    
    init(height: Double, myRadius: Double) {
        self.height = height
        super.init(myRadius: myRadius)
    }
    
    override func circumference() -> Double {
        return (2 * myRadius * myPi) / 2
    }
    
    override func area() -> Double {
        return (myRadius * myRadius * myPi) / 2
    }
    
    func volume() -> Double {
        return self.area() * height
    }
}

let objCylinder2 = HalfCylinder(height: 10, myRadius: 25)
objCylinder2.myRadius
objCylinder2.circumference()
objCylinder2.area()
objCylinder2.height
objCylinder2.volume()

Computed Properties 

  • In a class, we use let and var to store constant and variables. 
  • Swift also allowed us to have computed properties. Such properties are computed and do not have its own value. 
  • It is actually a function disguise as property 
  • The above example can be reconstructed with computed properties
class Circle3 {
    
    let myPi = 3.1415
    var myRadius:Double
    
    init(myRadius: Double) {
        self.myRadius = myRadius
    }
    
    var circumference: Double {
        return 2 * myRadius * myPi
    }
    
    var area: Double {
        return myRadius * myRadius * myPi
    }
}

let objCircle3 = Circle3(myRadius: 25)
objCircle3.myRadius
objCircle3.circumference
objCircle3.area
  • In the above example, circumference and area are considered computed properties. 
  • We can have getter and setter in computed properties The example above is basically a getter, it can be written as the followings:
class Circle4 {
    
    let myPi = 3.1415
    var myRadius:Double
    
    init(myRadius: Double) {
        self.myRadius = myRadius
    }
    
    var circumference: Double {
        get {
            return 2 * myRadius * myPi
        }
    }
    
    var area: Double {
        get {
            return myRadius * myRadius * myPi
        }
    }
}

let objCircle4 = Circle4(myRadius: 25)
objCircle4.myRadius
objCircle4.circumference
objCircle4.area

  • Computed properties in Swift class can have getter and setter 
  • In the example above, we need to create instance by providing a radius. However, if we have only the circumference or area. We can set those value and calculate the radius in reverse as shown in the following example.
  • Please note that when using setter, we use newValue as the new value of the computed properties. The code will compute the radius in reverse.
class Circle5 {
    
    let myPi = 3.1415
    var myRadius:Double
    
    init(myRadius: Double) {
        self.myRadius = myRadius
    }
    
    var circumference: Double {
        get {
            return 2 * myRadius * myPi
        }
        set {
            myRadius = newValue / ( 2 * myPi )
        }
    }
    
    var area: Double {
        get {
            return myRadius * myRadius * myPi
        }
        set {
            myRadius = sqrt(newValue/myPi)
        }
    }
}

let objCircle5 = Circle5(myRadius: 25)
objCircle5.myRadius
objCircle5.circumference
objCircle5.area

let objCircle6 = Circle5(myRadius: 25)
objCircle6.myRadius
objCircle6.circumference
objCircle6.area

objCircle6.circumference = 157
objCircle6.myRadius
objCircle6.circumference
objCircle6.area

objCircle6.area = 1963
objCircle6.myRadius
objCircle6.circumference
objCircle6.area

  • If we don't need computed properties but we would like to process some code before the variable is set and/or after the variable is set, we can use willSet an didSet keyword. 
  • We use willSet and didSet to define how the variable will trigger some code before or after it is set.
class PersonalHealth {
    
    var name: String {
        willSet {
            print("Welcome \(name)")
            print("Disclaimer: We under take no liability")
        }
        didSet {
            heightMetric = 0
            weightMetric = 0
        }
    }
    
    var metric: Character
    
    var heightMetric: Double {
        didSet {
            if self.metric == "e" {
                self.heightMetric = self.heightMetric * 0.3048
            }
        }
    }
    
    var weightMetric: Double {
        didSet {
            if self.metric == "e" {
                self.weightMetric = self.weightMetric * 0.453592
            }
        }
    }

    var bmi: Double {
        return weightMetric / (heightMetric * heightMetric)
    }
    
    init(name: String, metric: Character, height: Double, weight:Double) {
        
        self.name = name
        self.metric = metric
        self.heightMetric = height
        self.weightMetric = weight
    }
    
}

let myHealth1 = PersonalHealth(name: "John", metric: "a", height: 1.58, weight: 57)

myHealth1.name
myHealth1.heightMetric
myHealth1.weightMetric
myHealth1.bmi

myHealth1.name = "Tom"
myHealth1.metric = "e"
myHealth1.heightMetric
myHealth1.weightMetric
// In the above, when a new name is set, the weight and height is set to zero

myHealth1.heightMetric = 5.2
myHealth1.weightMetric = 125
myHealth1.metric
myHealth1.heightMetric
myHealth1.weightMetric
myHealth1.bmi
// In the above code, when you entered height and weight and the system detect that you have set the metric code to "e", it will automatically convert the height and weight to metric
  • In the example above, before a name is set, we show the welcome message with disclaimer. 
  • After a new name is set, we will set the height and weight to zero 
  • Whenever a height or weight is set, the system will check the metric code, if the code is equal to "e" (for English). The system will assume the data entered is in feet and pound and perform automatic conversion.

Optional Instance

  • When can use optional with instances, method, and properties Usually, we will include a optional marker ? after init, so if initialization failed the instance will be nil
class Circle6 {
    
    let myPi = 3.1415
    var myRadius:Double
    
    init?(myRadius: Double) {
        if myRadius != 0 {
            self.myRadius = myRadius
        } else {
            return nil
        }
    }
    
    var circumference: Double {
        get {
            return 2 * myRadius * myPi
        }
        set {
            myRadius = newValue / ( 2 * myPi )
        }
    }
    
    var area: Double {
        get {
            return myRadius * myRadius * myPi
        }
        set {
            myRadius = sqrt(newValue/myPi)
        }
    }
}

let myCircle1 = Circle6(myRadius: 5)
myCircle1?.myRadius
myCircle1?.area
myCircle1?.circumference

let myCircle2 = Circle6(myRadius: 0)
myCircle2?.myRadius
myCircle2?.area
myCircle2?.circumference

  • We can also use if and let to check if object is nil as follows

if let myCircle3 = Circle6(myRadius: 25) {
    print("Instances Set")
    myCircle3.myRadius
    myCircle3.circumference
    myCircle3.area
} else {
    print("error create object")
}

if let myCircle4 = Circle6(myRadius: 0) {
    print("Instances Set")
    myCircle4.myRadius
    myCircle4.circumference
    myCircle4.area
} else {
    print("error create object")
}

Classes and Reference Type

  • Classes and its instances/objects are reference data type. 
  • This means that when you create an instance/object and you assign the instance with another variable, you just pass the reference to the second variable instead of copying the instance to another variable.

let obj1 = Circle6(myRadius: 25.0)
obj1?.area
obj1?.circumference
obj1?.myRadius

let obj2 = obj1
obj2?.myRadius = 30
obj2?.myRadius
obj2?.area
obj2?.circumference

obj1?.myRadius
obj1?.area
obj1?.circumference

  • In the above example, when you assign obj2 with obj1, obj1 just pass its object reference to obj2. 
  • Both obj2 are referring to the same instance/object. 
  • Also notice that we declared obj2 as constant but we can still modified the properties inside obj2. This happens because obj2 stored not the object but the reference address of the instances created by obj1. 
  • However, you cannot assign other instance to obj2 again since it is a constant. 

Polyphormism

  • The most exciting about class and instances is its ability to act as same object in the super class. We can group objects under the same super class into a meaningful collection and perform functions or manipulate properties that are common between different objects. 
  • For example, we have another class called MainCircle, a sub class called MainCylinder which inherit from MainCircle and a subclass called Cone, also inherit from MainCircle. 
  • We can mixed instances to 2 types (MainCylinder and Cone) and act as circle, however, we cannot mixed and down cast both as cylinder or cone.

class MainCircle {
    var radius: Double
    let pi = 3.1415
    
    init?(radius: Double) {
        if radius != 0 {
            self.radius = radius
        } else {
            return nil
        }
    }
    
    var area: Double {
        get {
            return radius * radius * pi
        }
    }
    
    var circumference: Double {
        get {
            return 2 * radius * pi
        }
    }
}

class MainCylinder: MainCircle {
    var height: Double
    
    init?(radius: Double, height: Double) {
        if radius != 0 && height != 0 {
            self.height = height
            super.init(radius: radius)
        } else {
            return nil
        }
    }
    
    var volume: Double {
        get {
            return self.area * self.height
        }
    }
}

class Cone: MainCircle {
    var height: Double
    
    init?(radius: Double, height: Double) {
        if radius != 0 && height != 0 {
            self.height = height
            super.init(radius: radius)
        } else {
            return nil
        }
    }
    
    var volume: Double {
        get {
            return self.area * (self.height/3)
        }
    }
}

let arrayRoundObject = [MainCylinder(radius: 4.0, height: 10)!, MainCylinder(radius: 13.0, height: 16)!, Cone(radius:6.5, height: 14)!, Cone(radius: 7.5, height: 6.3)!]

  • Note: When creating an array such as the array above if your class init is optional then you need to add `!` at the end of init statement.


var totalNumberOfObject = 0
for eachObject in arrayRoundObject {
    print("Area is \(eachObject.area)")
    //print("Volume is \(eachObject.volume)") // This will produce error as now it recognize the object as super class MainCirlce
    // To get volume we need to case each object into their respective type
    if let isCylinder = eachObject as? MainCylinder {
        print("This is cylinder, volume is \(isCylinder.volume)")
    }
    if let isCone = eachObject as? Cone {
        print("This is cone, volume is \(isCone.volume)")
    }
    totalNumberOfObject += 1
}

print("Total number of objects = \(totalNumberOfObject)")

A collection of playgrounds file for this tutorial can be found at https://github.com/SwiftiCode/Swift-Brief-Note-Playground

*** End ***

Swift 2.2 Brief Introduction for Experienced Programmer - Part 3 - Function & Closure

Function and Closure 

Functions in Swift is a first class object. This means that it can be assigned to variables, passed into other function as argument or act as return from other function. Function can capture variables outside their local scope. Closure is the same as function except without name and closure expression can be very concise. 


Basic Function 


  • To create a function we use keyword func follow by () for arguments. We use -> to indicate that anything after the arrow is the return of the function.

  • The following function is the most basic function without argument and return.
func printHi() {
    
    print("Hi!")
}

printHi()
  • The following function requires one string argument only.
func printHello(name: String) {
    
    print("Hello \(name), how are you?")
}

printHello("Alex")
  • The following function requires one string argument and it return another string argument.
func printHi2(name: String) ->String
{
    return "Hello \(name), have a good day."
}
let message1 = printHi2("Tom")
message1

Return as Tuple 

  • Tuple is a group of variable grouped into a single variable. We can mixed different type of variables in a tuple including string.
var tupleExample1 = (voltage: 36.0, current: 9.0, resistance: 4)

tupleExample1.current
tupleExample1.resistance
tupleExample1.voltage
  • For example, we can perform calculation and return a set of related data. Lets assume we have an array of numbers to compute, we can return a set of related statistics as follows:
let dataSet1 = [23, 100, 50, 46]
func sumAll(dataSet: [Int]) -> (sum:Int, count: Int, average: Double)
{
    var count = 0
    var sum = 0
    
    for eachNumber in dataSet
    {
        sum += eachNumber
        count += 1
    }
    
    let average =  Double(sum) / Double(count)
    
    return (sum, count, average)
}


let result = sumAll(dataSet1)
result.average
result.count
result.sum
  • We can also use number instead of name. The sequence of number is in the same order as the return value starting with 0. See example below:
result.0 // Sum
result.1 // Count
result.2 // Average

Considering the example above, let's say that our data set is small but the number of data point in the data set may varies. Instead of using array, we can create a function that accept a set of integers with variable quantity. To indicate the variable quantity of data set we use ... after the data type in the argument. See example below:

func sumAll2(dataSet: Int...) -> (sum:Int, count: Int, average: Double)
{
    var count = 0
    var sum = 0
    
    for eachNumber in dataSet
    {
        sum += eachNumber
        count += 1
    }
    
    let average =  Double(sum) / Double(count)
    
    return (sum, count, average)
}

let result2 = sumAll2(12,32,5,23,78,3)
result2.count
result2.sum
result2.average

let result3 = sumAll2(123,234,543)
result3.count
result3.sum
result3.average

  • If we look at the example below, we create a result without entering any data set. In this case, count and sum return a zero but average return nan. This is because in Swift 0/0 will return nan (NotANumber)
let result4 = sumAll2()
result4.count
result4.sum
result4.average
  • To avoid a nan return, we will modified the program to the following:
func sumAll3(dataSet: Int...) -> (sum:Int, count: Int, average: Double)
{
    var count = 0
    var sum = 0
    var average = 0.0
    
    for eachNumber in dataSet
    {
        sum += eachNumber
        count += 1
    }
    
    let averageTemp =  Double(sum) / Double(count)
    
    if !(averageTemp.isNaN) {
        average = averageTemp
    }
    
    return (sum, count, average)
}

let result5 = sumAll3()
result5.count
result5.sum
result5.average


  • We can also created nested functions.  
  • The following example use the common computation of voltage = current X resistance. The computation is as follows:


    voltage = current X resistance
    current = voltage / resistance
    resistance = voltage / current

  • Instead of creating 3 different function, we create a main function that accept input base on the formula above. input1 is the first value and input2 is the second value. 
  • The main function also accept a ask code, if you are asking for voltage use "v", if you are asking for current use "i" and if you are asking for resistance use "r" 
  • In this example, we nest the 3 function into a main function. In the main function user need to input the first value and second value together with ask code. 
 See example below:

func produceVIR(input1: Double, input2: Double, ask: String ) -> Double?
{
    var answer: Double? = nil
    
    func returnV(inputI: Double, inputR: Double)
    {
        answer = inputI * inputR
    }
    
    func returnI(inputV: Double, inputR: Double)
    {
        answer = inputV / inputR
    }
    
    func returnR(inputV: Double, inputI: Double)
    {
        answer = inputV / inputI
    }
    
    switch ask {
    case "v": returnV(input1, inputR: input2)
    case "i": returnI(input1, inputR: input2)
    case "r": returnR(input1, inputI: input2)
    default: print("code not recognize")
    }
    
    return answer
}

let myI1 = 13.0
let myR1 = 20.0
if let myV1 = produceVIR(myI1, input2: myR1, ask: "v")
{
    print("The voltage with current of \(myI1)A and \(myR1)ohm is \(myV1)v")
} else {
    print("Something wrong with your ask code. The system can only accept i, r or v in lower case")
}

let myV2 = 240.0
let myR2 = 10000.0
if let myI2 = produceVIR(myV2, input2: myR2, ask: "i")
{
    print("The current with voltage of \(myV2)v and \(myR2)ohm is \(myI2)A")
} else {
    print("Something wrong with your ask code. The system can only accept i, r or v in lower case")
}


let myV3 = 240.0
let myI3 = 0.001
if let myR3 = produceVIR(myV3, input2: myI3, ask: "r")
{
    print("The resistance with voltage of \(myV3)v and \(myI3)A is \(myR3)ohm")
} else {
    print("Something wrong with your ask code. The system can only accept i, r or v in lower case")
}

let myV4 = 240.0
let myI4 = 0.001
if let myR4 = produceVIR(myV4, input2: myI4, ask: "g")
{
    print("The resistance with voltage of \(myV4)v and \(myI4)A is \(myR4)ohm")
} else {
    print("Something wrong with your ask code. The system can only accept i, r or v in lower case")
}
  • We can assign a function to a variable
let vIR = produceVIR
let v = vIR(13.0, input2: 20.0, ask: "v")
v
  • We can use another function within a function. The example below create a function that return the area and perimeter of a square.
func square(lengthOfSides: Double) -> (area:Double, perimeter: Double)
{
    var area = 0.0
    var perimeter = 0.0
    
    area = lengthOfSides * lengthOfSides
    perimeter = lengthOfSides * 4
    return (area, perimeter)
}

let sq1 = square(5)
sq1.area
sq1.perimeter
  • The next function calculate the volume of a cube with equal sides. Effectively, we can use the previous function and multiple by height
func cubeVol(side:Double, height: Double) -> Double
{
    var vol = 0.0
    
    
    vol = square(side).area * height
    return vol
    
}

cubeVol(5,height:3)
  • We can also create a function that return another function as its value. Such function are first class function
func makeHalf() -> ((Double, Double) ->Double)
{
    
    func halfCube(side:Double, height: Double) -> Double
    {
        return cubeVol(side, height: height)/2
        
    }
    return halfCube
}

var makeHalfcube = makeHalf()
makeHalfcube(5, 3)
  • Another example of using first class function and returning function as its value. In this example, we just input ask string and we get return as a function
func produceVIRFormula(ask: String ) -> ((Double, Double) -> Double)?
{
    
    
    func returnV(inputI: Double, inputR: Double) -> Double
    {
        return inputI * inputR
    }
    
    func returnI(inputV: Double, inputR: Double) -> Double
    {
        return inputV / inputR
    }
    
    func returnR(inputV: Double, inputI: Double) -> Double
    {
        return inputV / inputI
    }
    
    switch ask {
    case "v": return returnV
    case "i": return returnI
    case "r": return returnR
    default: print("ask code not recognize"); return nil
    }
    
}

let myI5 = 13.0
let myR5 = 20.0
if let myFormula5 = produceVIRFormula("v")
{
    let myV5 = myFormula5(myI5, myR5)
    print("The voltage with current of \(myI5)A and \(myR5)ohm is \(myV5)v")
} else {
    print("Something wrong with your ask code. The system can only accept i, r or v in lower case")
}

let myV6 = 240.0
let myR6 = 10000.0
if let myFormula6 = produceVIRFormula("i")
{
    let myI6 = myFormula6(myV6, myR6)
    print("The current with voltage of \(myV6)v and \(myR6)ohm is \(myI6)A")
} else {
    print("Something wrong with your ask code. The system can only accept i, r or v in lower case")
}


let myV7 = 240.0
let myI7 = 0.001
if let myFormula7 = produceVIRFormula("r")
{
    let myR7 = myFormula7(myV7, myI7)
    print("The resistance with voltage of \(myV7)v and \(myI7)A is \(myR7)ohm")
} else {
    print("Something wrong with your ask code. The system can only accept i, r or v in lower case")
}

let myV8 = 240.0
let myI8 = 0.001
if let myFormula8 = produceVIRFormula("j")
{
    let myR8 = myFormula8(myV8, myI8)
    print("The resistance with voltage of \(myV8)v and \(myI8)A is \(myR8)ohm")
} else {
    print("Something wrong with your ask code. The system can only accept i, r or v in lower case")
}

let myV9 = 0.0
let myI9 = 0.0
if let myFormula9 = produceVIRFormula("r")
{
    let myR9 = myFormula9(myV9, myI9)
    print("The resistance with voltage of \(myV9)v and \(myI9)A is \(myR9)ohm")
} else {
    print("Something wrong with your ask code. The system can only accept i, r or v in lower case")
}
  • A function can take another function as one if its argument.   
  • In the following example, we have a function to check if a number is even and we have a function called processData. 
  • We use processData to accept a list of numbers and we accept a function as argument to evaluate a list. Any function that accept Int and produce a boolean is acceptable.
func isEven (number: Int) -> Bool {
    
    if Double(number) % 2 == 0 {
        return true
    } else {
        return false
    }
}

func processData(dataList: [Int], evaluate: Int -> Bool)  {
    
    for eachData in dataList {
        
        if eachData < 10000 {
            
            if evaluate(eachData) {
                print(eachData)
            }
            
        }
    }
    
}

let sampleData = [25, 54, 67, 254, 254754, 457, 36568, 142, 254, 36563, 47, 589]

processData(sampleData, evaluate: isEven)

Closure 

Closure is a block of code similar to function except without name. Closure can capture variables in the same scope where it was created. 

The syntax of closure is as follows: 
    { (argument: datatype) -> returnDataType in 
       ...the rest of the code... 

We use closure to implement a generic function. For example, an array has a map function that accepts closure. You can apply any type of code in this map method. The map method will iterate through every element in the array and applied the closure you supply to each element.   The following closure just add 1 for each element

let myArrayNumbers = [1, 2, 3, 4, 5]
let newArray1 = myArrayNumbers.map({ (no: Int) -> Int in
    return no + 1})

newArray1
myArrayNumbers
  • The following closure multiple each element by 14
let newArray2 = myArrayNumbers.map({ (no: Int) -> Int in
    return no * 14})

newArray2
myArrayNumbers
  • The following closure filter out the even number change change all odd number to 0
let newArray3 = myArrayNumbers.map({ (no: Int) -> Int in
    if no % 2 == 0 {
        return no }
    else { return 0 }
})

newArray3
myArrayNumbers

Simplified Closure
  • We can simplified the previous closure as follows:
let newArray4 = myArrayNumbers.map({ (no: Int) -> Int in return no * 14})
newArray4
  • When a closure type is known, we can simplified it by omitting the argument type and return type
let newArray5 = myArrayNumbers.map({ no in return no * 14})
newArray5
  • We can also omit return
let newArray6 = myArrayNumbers.map({ no in no * 14})
newArray6
  • We can refer to parameters by number instead of by name. We can also omit in
let newArray7 = myArrayNumbers.map({ $0 * 14})
newArray7
  • Finally, when the closure is the only argument, we can omit ()
let newArray8 = myArrayNumbers.map{ $0 * 14 }
newArray8

A collection of playgrounds file for this tutorial can be found at https://github.com/SwiftiCode/Swift-Brief-Note-Playground

*** End ***

Swift 2.2 Brief Introduction for Experienced Programmer - Part 2 - Control Flow

Control Flow 

  • For conditional branch we use if and switch.   
  • For loops we use for-inwhile and repeat-while.   
  • Parentheses around the condition or loop variable are optional. 
  • Braces around the body are required. 

if  Syntax: 
     if (Boolean expression) 
          {...} 
          else 
          {...} 
          elseif 
          {...}

See example below: 
     if someVar3 >= 50 { 
          //Do something for pass 
      } else { 
           //Do someThing for fail 
      } 

Below is an example using if:

var student1 = 40
var student2 = 80

if student1 > 50
{
    print("Pass")
}
else
{
    print("Fail")
}

if student2 > 50
{
    print("Pass")
}
else
{
    print("Fail")
}

  • Please note that previously in C, any variable contains a 1 is considered true. However, in Swift, conditional expression must be evaluated to true or false.

let checksum1 = 1
//if checksum1 { print("0k") } else { print("Not OK") }  //This expression failed because checksum1 is 1 not True

let checksum2 = true
if checksum2 { print("0k") }  else { print("Not OK") }

Optional Variable 

Now, we would like to introduce optionals. Optionals are variable that could be nil (no value at all). The syntax of these variables are added with ? after the variable names and data type declaration.

  •  var someData = 12 is not optional 
  •  var someData: Int? is optional

To test optional, we use two methods. One of them is to use ?? as conditional test, if test failed, a substitute will be use

See example below:

let someVar3: Int? = nil
let someVarCheck1 = someVar3 ?? 0  //In this statement if someVar3 is nil, we will assign 0 to someVarCheck1

  • Another way to test optional is to use if and let.

let someVar4: Int? = nil
if let someVarCheck2 = someVar4
{
    print(someVarCheck2)
}
else
{
    print("No Values in someVar4")
}

  • Another example

var optionalNumber: Int? = 3
if let checkNum = optionalNumber
{
    print("Got value")
}
else
{
    print("No Value")
}

optionalNumber = nil
if let checkNum = optionalNumber
{
    print("Got value")
}
else
{
    print("No Value")
}

  • If the optional is nil, the let statement is false, thus it will skipped to else statement 
  • Note: Both methods of testing optional are very common in Swift programming. 
  • If an optional must not be nil then we should use `??` to substitute a default value when the optional happen to be nil. 
  • If we just want to trap an error using optional than we should use if and let method. 

Switches 

We use switch and case to support multiple conditional testing. Please note that the testing must be exhaustive, therefore, we need to add a `default` as a catch all condition at the last conditional check. 

switch keyVariable 

     case (number or string): code 
     case (number or string): code 
     default: doSomeOtherThing 


  • Please note that default is required, no break is necessary, and the testing of each condition must be exhaustive. 
  • We usually use switch where there are few option that we want to test.

let option = 5

switch option {
    
case 1 : print("You have selected option 1")
case 2 : print("You have selected option 2")
case 3 : print("You have selected option 3")
case 4 : print("You have selected option 4")
case 5 : print("You have selected option 5")
default: print("Your selection is invalid!")
    
}

  • Another example
var someNum1 = 3000
switch someNum1
{
case 1000 : let result1 = "your case is 1000"
case 2000 : let result1 = "your case is 2000"
case 3000, 4000 : let result1 = "your case is 3000 or 4000"
case 5000: let result1 = "your case is 5000"
default : let result1 = "you have no case"
}

  • We can use string for switch, we can use let x where x.hasPrefix("somePrefix"): as a conditional text for string.
let food = "curry rice"
switch food {
    
case "chicken salad" : print("You have chicken rice")
case "duck rice" : print("You have duck rice")
case let x where x.hasPrefix("curry"): print("You like curry")
case "fried chicken": print("You have fried chicken")
default: print("Your food choice is something we don't know")
    
}

  • let can be used with where in a pattern to assign the value that matched that part of a pattern to a constant Another example
let fruits = "waterchestnut"
switch fruits {
case "orange":
    let fruitComm = "This is orange"
case "apple":
    let fruitComm = "An Apple a day"
case let x where x.hasPrefix("water"):
    let fruitComm = "Is this fruit \(x) taste watery?"
default:
    let fruitComm = "Fruit is good for you."
}

  • We can also allow multiple condition to flow through as the example below:
let partNumber = "7500A"
switch partNumber {
    
case "6100A", "7500A", "7000C" : print("The part \(partNumber) is in our store")
default : print("We do not sell this part")
    
}

for-in

  • We use for and in to iterate through every items in a collection. Iterating through an array:
let someArray1 = [12, 34, 65, 87, 23, 87]
var sum: Int = 0

for eachItem in someArray1 {
    sum += eachItem
}

print(sum)

  • We can also use dictionary to iterate each set of item
let someDictionary1 = [1:"A1", 2:"B2", 3:"C3"]
var total = 0
for (key, description) in someDictionary1 {
    
    print(key)
    print(description)
    total += 1
    
}

print(total)

  • We can also have nested loop using for and in
  • We can use range indicator such as ..< or ...
  • For example, we use 0..<100 to indicate a range of number 0 to 99. This statement include 0 but exclude 100. 
  • We use 0...100 to indicate the range of number 0 to 100. 
  • To exclude the lower range we can just start the lower value from where we want such as: 1..<99 to exclude 0.
Please check the playground for more examples.

while, repeat-while
  • Usually we have while and do-while. In Swift, we use while and repeat-while. We list the basic example where every programmer knows

var sum1 = 0
var n1 = 1

while n1 <= 100 {
    
    sum1 += n1
    n1 += 1
}

print(sum1)

  • Our next example use repeat and while. This is similar with do-while, just replace do with repeat.

var sum2 = 0
var n2 = 1

repeat {
    
    sum2 += n2
    n2 += 1
    
} while n2 = 100

print(sum2)

  • Usually we use repeat-while to run the loop at least once

var sum3 = 0
var n3 = 20
repeat {
    
    sum3 += n3
    n3 += 1
    
} while n3 = 20

print(sum3)

  • We also use repeat-while to run the loop and check for condition as shown in the example below.

var sum4 = 0
var additive = 20
repeat {
    
    sum4 += additive
    
} while sum4 < 100

print(sum4)

A collection of playgrounds file for this tutorial can be found at https://github.com/SwiftiCode/Swift-Brief-Note-Playground

*** End ***

Swift 2.2 Brief Introduction for Experienced Programmer - Part 1 - Basics

Part 1 - Basics, Variables, Data Types and Collections 

This brief note is for programmers who already know the basics of object oriented programming. The programmer may already be familiar with other programming languages but want to learn about Swift Programming.

This guide is based on Swift 2.2.

Print to Console 

  • To print text, use print function. Such as print("Enter some text here")
print ("Hello Word!")
  • We can also assign the message to a string variable as follows:
let message = "Hi Playground"
print(message)

Basic Syntax 

  • In Swift, semi-colon (;) is not necessary unless you want to put multiple statement into a single line.
let someVar1 = 6; let someVar2 = 23.4 // Semi-colon is required in this situation when you want to place 2 separate code on a single line

Create Constants 

  • We use keyword let to create constant - values that will not change 
  • Constant must be declared before being used.
let constant1 = 23
constant1
//constant1 = 43 // This line will caused error as constant cannot be reassigned

Create Variable 

  • We use keyword var to create variable - values that will be changed from time to time 
  • Variable must be declared before being used.
var variable1 = 45
variable1
variable1 = 76
variable1

Variables & Type Inference 

Swift is a type safe language. We must assign a value that fits the data type of a variable. Swift will flag any un-match type. During constant or variable creation, the compiler will infers the data type of the constant or variable base on the type of its value. There is no need to define the data type explicitly. After the creation of a variable, the system will only allow values of the same type when reassigning values to the same variable.

For integer and floating point, Int and Double will be the preferred default. If we provide an expression instead of literal value, the system will infer the most appropriate data type for us.

var variable2 = 26
variable2
variable2 = 64
variable2
//variable2 = 58.4 // This line will generate error since the type of the values is different from the type of variable2
variable2

let variable2a = 25 * 1.0 // The variable2a will be automatically declared as Double

Specified a Type Explicitly 

  • Programmers can explicitly provide the variable type by providing a colon follow by type after the variable name
let variable3:Double = 54
variable3
let variable4:Float = 4
variable4

Basic Data Types 

Basic Types
  • Integers - Int 
  • Floating Point - Double, Float 
  • Boolean - Bool 
  • Text - String 

Collection Types
  • Array 
  • Set
  • Dictionary 
  • Tuples - An assorted set of related values group under a name. 

Others
  • Optional - Any data type that can be nil
let variable5a: Int = -8
let variable5b: UInt = 6
let variable5c: Float = 3.1415
let variable5d: Double = 2.718
let variable5e: Bool = true
let variable5f: String = "This is a string"

Data Type Conversion 

  • To convert from one data type to another we must create a variable of our desire data type and explicitly convert the value using dataType() syntax.
let variable5 = 2564
variable5
let variable6 = Double(variable5) + 0.45
variable6
let variable7 = String(variable6)
variable7
  • We can include variable inside our print function using \(expression)
let store1 = 25
let store2 = 54
let statement1 = ("We have \(store1) items in store 1 and \(store2) items in store 2. In total, we have \(store1 + store2) items")

let variable8 = 765
var variable9 = 43

let message2 = "The first number is "
let message3 = message2 + String(variable8)
message3
let message4 = "The next number is \(variable9)"
let message5 = "The total of \(variable8) and \(variable9) is \(variable8 + variable9)"
print(message5)

Arrays 

  • To create arrays, we use brackets [] to include items in an array such as: var arrayName = ["item1", "item2"....."lastitem"]. Please note that index start with 0.
var nameList = ["John", "Peter", "Mathew", "Christopher", "Danny"]
nameList[0]
nameList[1]
nameList[2]
nameList[3]
nameList[4]
  • To provide total number of element
nameList.count
  • To add new element
nameList.append("Thomas")
nameList[5]
  • To change old element
nameList[2]
nameList[2] = "Mark"
nameList[2]
  • To remove an element
nameList.removeAtIndex(4)
nameList[4]  //previous added nameList[5] become nameList[4]
//nameList[5] // generate error since nameList[5] become nameList[4]
  • To insert an element right in front of array, all other element pushed down the array
nameList.insert("Paul", atIndex: 0)
nameList[0]
nameList[1]
nameList[2]
  • Display last item
nameList.last
  • Remove last item of array
nameList.removeLast()
nameList.last
  • Display the last index + 1, you can also use this number as the total count. Similar to `.count`
nameList.endIndex
  • Display the start index
nameList.startIndex
  • To find out the index of a particular element
nameList.indexOf("Peter")
  • To create empty arrays
var nameList2 = [String]()
  • To populate empty arrays
nameList2 += ["Test1", "Test2"]
nameList2[0]
nameList2[1]
nameList2.append("Test3")
nameList2[2]
  • If the data type can be inferred then you can create an empty array without indicating the data type. We can also use this method to clear all the data inside the array while maintaining its data type. 
nameList2 = []
//nameList2[0] // This statement will generate error since all data had been cleared.

Dictionary 

  • To create dictionary use brackets and colon to include key and definition in dictionary such as: var dictionaryName = ["key1":"definition1", "key2":"definition2"....."keylast":"definitionlast"]
var dictionaryList1 = [1:"one", 2:"two", 3:"three", 4:"four"]
dictionaryList1[3]
  • To add definition
dictionaryList1[5] = "five"
  • Create an empty dictionary
var dictionaryName1 = [String:String]()
  • To populate the empty dictionary
dictionaryName1 = ["key1":"definition1",  "key2":"definition2", "keylast":"definitionlast"]
dictionaryName1["key2"]
  • To add definition
dictionaryName1["key3"] = "definition3"
  • To create empty dictionary, you need to specify the variable type
var dictionaryName2 = [String:Float]()
  • To populate empty dictionary
dictionaryName2 = ["pi": 3.1415,"e": 2.71828]
  • If type information can be inferred then you can create dictionary without variable type
dictionaryName2 = [:]
  • Another example
var alphabetList = [ "A":"Alpha", "B":"Bravo" ]
alphabetList["B"]
  • To add additional definition
alphabetList["C"] = "Charlie"
alphabetList["C"]
alphabetList["J"] = "Juliet"
alphabetList["H"] = "Hawk"
  • To list the total number of definitions
alphabetList.count
  • To change a definition
alphabetList["H"]
alphabetList["H"] = "Hotel"
alphabetList["H"]
  • To find the index for a definition
let indexForJuliet = alphabetList.indexForKey("J")
indexForJuliet
print(alphabetList[indexForJuliet!])
  • To remove a definition by index
alphabetList.removeAtIndex(indexForJuliet!)
alphabetList[indexForJuliet!] // index will change since Juliet has been erased
  • To remove a definition by key
alphabetList.removeValueForKey("H")
alphabetList.count
alphabetList["H"]

A collection of playgrounds file for this tutorial can be found at https://github.com/SwiftiCode/Swift-Brief-Note-Playground

*** End ***

Thursday, May 19, 2016

iOS 9.3.2 Available

Hi there,

iOS 9.3.2 is available now. The are no new features except bug fixes.

At the same time there is also an upgrade for iTunes. Please note that the latest iTunes removed the functionality of resetting play count.


Wednesday, May 11, 2016

Swift 3.0 Release Date

According to the TNW post, Swift 3.0 will be release for developer preview on 12 May 2016. TNW got the information from the blog post Swift 3.0 Release Process. There are few pointers to note for developers.

  • I believe this is the first major release since Swift is open source.
  • Developer preview is also available for Linux platform.
  • There will be major changes to the core libraries.
  • Swift 3.0 will introduce package manager which will attempt to provide cross platform support.
  • Old C programming syntax such as i++ and `for` loop will be removed.
  • Swift 3.0 is also considered to be a major stable release.
  • This is the first version that includes Linux core libraries.
For further information, please visit the open source site https://swift.org/.
To learn about Swift 3 release process check out this blog post Swift 3.0 Release Process
To find out what are the changes to Swift 3.0 in details, please check out Apple's Github page called Swift-evolution.