Basic

Syntax

// variablevar number = 6var title : String?// const value, should be initialized before use it, can't be changed after its definitionlet speed = 200 let name : String? = nil

Base data type

TypeDesc
UInt8UInt8.min is 0, UInt8.max is 255
IntOn the 32-bit platform, it’s as Int32; On the 64-bit platform, it’s as Int64.
UintOn the 32-bit platform, it’s as UInt32; On the 64-bit platform, it’s as UInt64.
Double64-bit floating-point number
Float32-bit floating-point number
Booleantrue or false

Numeric

/* Numeric Literals */// They are the same number, in another word, their values are the same. let decimalInteger = 17let binaryInteger = 0b10001let octalInteger = 0o21let hexadecimalInteger = 0x11// Optional exponent (exp)1.25e21.25e-2// pad with extra zeros and underscores to make them easier to read.let paddedDouble = 000123.456let oneMillion = 1_000_000let justOverOneBillion = 1_000_000.000_000_1/* Numeric Type Conversion */// Type automatic convertlet a : UInt16 = 2000let b : UInt8 = 1    // Different type can't be sum togetherlet c = a + b        // Here, system use b to create a new UInt16 object, so this new object can sum with a.// Type force convertlet three = 3let num = 0.14159let pi = Double(three) + num  // conversions between integer and floating-point numeric types must be made explict.// Truncatelet integerPi = Int(pi)// The rules for combining numeric constants and variable are different from the rules for numeric literals.// Number literals don’t have an explicit type in and of themselves.

Type Aliases

typealias MyInt16 = UInt16var num : MyInt16 = MyInt16.min  // it's actually calls the UInt16.min

Tuples

let http404Error = (404, " Not Found")          // compose a tuple let (statusCode, statusMessage) = http404Error  // decompose a tuplelet (justTheStatusCode, _) = http404Error       // use a underscore(_) to ignore other valueslet statusCodeByIndex = http404Error.0          // get the tuple's individual element value by index, start at 0// name the tuple's individual elementlet http200Status = (statusCode : 200, description : "OK")let status200 = http200Status.statusCodelet description200 = http200Status.description

Optional : variable can be a value or nil. Just add a ‘?’ after the variable’s type.  nilmeaning “the absence of a valid object.”

only optional type can be nil.

const value should not be nil, it has no specific meaning in application.

var name:String? = "Hello"// Because the initializer might be fail, it returns an optional Int (Int?), rather than an Int.     let num = Int("123")var answer : Int?   // the answer is automatically set to nil.// In Objective-C, nil is a pointer to a nonexistent object. // In Swift, nil isn’t a pointer—it’s the absence of a value of a certain type.// Include multiple condition// If any of the values in the optional bindings are nil or any Boolean condition evaluates to false, the whole if statement’s condition is considered to be false.if let firstNum = Int("4"), let secondNum = Int("5"), firstNum < secondNum && secondNum < 100 {        print("\(firstNum) < \(secondNum) < 100")}let hobby : String?        // ordinary optionallet myHobby = hobby!       // must require a exclaimation point to unwrap the object.// An implicitly unwrapped optional as giving permission for the optional to be force-unwrapped if neededlet address : String!      // implicitly option. the name can be accessed when it is nil and without exclaimation point.let hisAddress = address   // it is permitted, no need for an exclaimation point.// we are recommanded to use the ordinary optional in development.// because the implicitly optional can easily be out of control.// ######## error #########// this will trigger a runtime errorvar str : String! = nilprint(str.count)// this will trigger a runtime errorvar bag : String?print(str!.count). // 'str!' is nil, so it can't be accessed. // this will trigger a compiler errorvar pack : String?print(str.count)  // str is an ordinary option, need an unwrap(!).// #######################

Function’s argument and its label

  • use argument label

    func addTwo(arg1 a : Int, arg2 b : Int) -> Int {  let c = a + b  return c}let sum = addTwo(arg1: 4, arg2: 28)
  • Tell argument’s name apparently

    func addTwo(a : Int, b : Int) -> Int {  let c = a + _b  return c}let sum = addTwo(a: 4, b: 28)
  • use [ _ ] to pass over the label (Recommended)

    func addTwo(_ a : Int, _ b : Int) -> Int {  let c = a + b  return c}let sum = addTwo(4, 28)
  • Function’s define and invoke no need to be sequenced. It can be invoked before it’s define.

    // invoke function goToSchool()//function definitionfunc goToSchool() {    print("I go to school.")}

Object Oriened

Class

class Person {    var name = "neo"    var age = 0        init () {}    init (_ name : String, _ age : Int) {        self.name = name        self.age = age    }}// use different init function to create object.var a = Person()var b = Person("Mike", 26)print(a.name + " " + String(a.age))print(b.name + " " + String(b.age))

Optional

class BlogPost {    // title can be String or nil    var title : String?    }let post = BlogPost()print(post.body + " hello!")//post.title = "yo"// Optional Bindingif let actualTitle = post.title {    print(actualTitle + " Hey")}else {        print("post.title is \(post.title)")}// Testting for nilif post.title != nil {    print(post.title! + " not nil") // exclaimation '!' means force unbox }if post.title == nil {    print("It's nil")}// Implicity optionalvar name : String! = "Amy" // '!' means that implicity optionalif name != nil {        // no need to use '!'        print(name + " not nil")}

Initializer

  • The rule of initializer

    1. A designated initializer must call the designated initializer from the immediately superclass.

      class Worker : Person {    override init () {        super.init()        print("subclass's designated initializer")    }                // it has no conflict with the superclass's convenience method.      init (customName : String, age : Int) {                // designated initializer call the designated initializer from superclass.                super.init(name : customName)                self.age = age        print("subclass's designated initializer with two parameters")    }}class Person {    var name = "neo"    var age = 0        init () {        age = 3        name = "ha"    }        init (name : String) {        self.name = name    }        convenience init (customName : String, age : Int) {        self.init(name : customName)        self.age = age    }}
    2. A convenience initializer must call another designated initializer from the same class.
    3. A convenience initializer must ultimately call a designated initializer.
  • designated initializer

    init () {        age = 3        name = "ha"    }
    init(_ name : String, _ age : Int) {        self.name = name        self.age = age}
  • convenience initializer

    if we want to invoke the designated initializer self.init() in a newly init method, we should add a keyword ‘convenience’ to decorate this newly method. (The reason why we use the ‘convenience’ keyword)

    convenience init(name : String) {        self.init()    self.name = name}
  • Inheritance

    Swift only permit single inheritance

    class Car {    var topSpeed = 200    func drive() {        print("Drive at \(topSpeed)")    }}// inheritanceclass FutureCar : Car() {        // the method belong to current class        func fly() {        print("Fly at \(topSpeed + 20)")        }}let myRide = Car() // create an instance from the class 'Car'.myRide.drive()let hisCar = FutureCar()hisCar.fly()       // method create by the subclass.
  • Polymorphism

    • Override

      The method has the same name but the arguments’ type or count are different.

      If we call with different types or count of arguments , the phenomenons(results) are different.

      class Car {    var speed = 200    func drive() {        print("Drive at \(speed)") // the 'speed' can be use in this class 'Car'    }    func drive(_ speed : Int) {        print("Drive at \(speed)") // the 'speed' can be only used in this func    }}let myCar = Car()myCar.drive()myCar.drive(160)
      // another casegoToSchool()goToSchool("Mike")goToSchool("Micle", "Jhon")goToSchool(15)func goToSchool() {    print("I go to school.")}func goToSchool(_ peoleA : String) {    print("I go to school with \(peoleA).")}func goToSchool(_ peopleA : String, _ peopleB : String) {    print("I go to school with " + peopleA + " and " + peopleB + ".")}func goToSchool(_ speed : Int) {    print("I go to school in a speed of \(speed).")}

      The subclass define a same method already in the superclass, but the implement of this method is different from that implemented in the superclass. Use the key word ‘override’

      class Car {    var speed = 200    func drive() {        print("Drive at \(speed)")    }}// inheritanceclass FutureCar : Car() {    // override the method from the superclass.        override func drive() {            print("Drive at \(speed + 5)")        }}let myRide = Car()//create an instance from the class 'Car'.myRide.drive()let hisCar = FutureCar()hisCar.drive()    //method override by the subclass.

Error Handling

Two way to solve the error on runtime

  • throws

    func doSomething() throws {    // Here may or may not throw an error}
  • do try catch

    do the right things to face the error.

    do {    try makeSandwich()    // no error was thrown    eatSandwich()} catch SandwichError.outOfCleanDishes {    // an error was thrown  washDish()} catch SandwichError.missingIngredients(let ingredients) {    // an error was thrown  buyGroceries(ingredients)} catch {    // catch other errors}

    ## Assertion & Precondition

    A assertion or precondition indicates an invalid program state, there’s no way to catch a failed assertion.

    // Assertionlet age = -3assert(age >= 0, "Age can't be less than 0") // (the condition, the message to be shown when the condition is false)assert(age >= 0)      // omit the message, it's ok.assertionFailure("Age can't be less than 0")  // when the code already check the failure, use the assertionFailure to show message directly.// Preconditionlet index = -1precondition(index >= 0, "Index must be greater than 0")precondition(index >= 0)preconditionFailure("Index must be greater than 0")// If you compile in unchecked mode (-Ounchecked), preconditions aren’t checked.But the assertion still check.// Assertion check in debug environment, not check in realease environment.// Precondition check in debug environment and release environment.// Use fatalError(_ :file:line:) to halt execution// During prototyping and early development to create stubs for functionality that hasn’t been implemented yet,write a fatalError as the stub implementation.// if the code use the functionality which hasn't been implemented, that will result in a fatal error. It will remind us to implement the function or method.fatalError("Unimplemented")