关于swift:Swift-Learning-Summary-Basics

20次阅读

共计 8671 个字符,预计需要花费 22 分钟才能阅读完成。

Basic

Syntax

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

Base data type

Type Desc
UInt8 UInt8.min is 0, UInt8.max is 255
Int On the 32-bit platform, it’s as Int32; On the 64-bit platform, it’s as Int64.
Uint On the 32-bit platform, it’s as UInt32; On the 64-bit platform, it’s as UInt64.
Double 64-bit floating-point number
Float 32-bit floating-point number
Boolean true or false

Numeric

/* Numeric Literals */
// They are the same number, in another word, their values are the same. 
let decimalInteger = 17
let binaryInteger = 0b10001
let octalInteger = 0o21
let hexadecimalInteger = 0x11

// Optional exponent (exp)
1.25e2
1.25e-2

// pad with extra zeros and underscores to make them easier to read.
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneBillion = 1_000_000.000_000_1

/* Numeric Type Conversion */
// Type automatic convert
let a : UInt16 = 2000
let b : UInt8 = 1    // Different type can't be sum together
let c = a + b        // Here, system use b to create a new UInt16 object, so this new object can sum with a.

// Type force convert
let three = 3
let num = 0.14159
let pi = Double(three) + num  // conversions between integer and floating-point numeric types must be made explict.

// Truncate
let 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 = UInt16

var 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 tuple

let (justTheStatusCode, _) = http404Error       // use a underscore(_) to ignore other values

let statusCodeByIndex = http404Error.0          // get the tuple's individual element value by index, start at 0

// name the tuple's individual element
let http200Status = (statusCode : 200, description : "OK")

let status200 = http200Status.statusCode
let 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 optional
let 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 needed
let 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 error
var str : String! = nil
print(str.count)
// this will trigger a runtime error
var bag : String?
print(str!.count). // 'str!' is nil, so it can't be accessed. 

// this will trigger a compiler error
var 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 definition
    func 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 Binding
if let actualTitle = post.title {print(actualTitle + "Hey")
}
else {print("post.title is \(post.title)")
}

// Testting for nil
if post.title != nil {print(post.title! + "not nil") // exclaimation '!' means force unbox 
}
if post.title == nil {print("It's nil")
}

// Implicity optional
var name : String! = "Amy" // '!' means that implicity optional
if 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)")
        }
    }
    
    // inheritance
    class 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 case
      goToSchool()
      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)")
          }
      }
      
      // inheritance
      class 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.

    // Assertion
    let age = -3
    assert(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.
    
    // Precondition
    let index = -1
    precondition(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") 

正文完
 0