Swift3.0基础部分(The Basics)(二)

作者: Mustard_Buli | 来源:发表于2016-07-11 14:45 被阅读90次
    类型安全和类型推断(Type Safety and Type Inference)
    • Swift是一个类型安全的语言,所以会在编译的时候会检查类型不匹配的错误。这么做可以尽可能早的在开发过程中发现错误。
    • 类型检查帮助避免在不同类型的值的错误。虽然这样,但也不意味着必须把每个变量(常量)的类型写出来。因为Swift使用类型推断来给出合适的类型。
    let meaningOfLife = 42
    //meaningOfLife is inferred to be of type Int
    

    当不声明一个浮点型时,默认是Double类型。

    let pi = 3.14159
    //pi is inferred to be of type Double
    let anotherPi = 3 + 0.14159
    //anotherPi is also inferred to be of type Double
    
    数字型的字面值(Numeric Literals)
    • 整型的字面可以这么写:
      • 十进制:不需要前缀
      • 二进制:前缀为"0b"
      • 八进制:前缀为"0o"
      • 十六进制:前缀为"0x"

    以下这些的值都是17

    let decimalInteger = 17
    let binaryInteger = 0b10001
    let octalInteger = 0o21
    let hexadecimalInteger = 0x11
    
    • 浮点型的字面可以为十进制(没有前缀),也可以为十六进制(前缀为"0x")。十进制数用大写或者小写的e表示指数,十六进制数用大写或小写的p表示指数。
      十进制:

      • 1.25e2 means 1.25 x 10^2, or 125.0.
      • 1.25e-2 means 1.25 x 10^(-2), or 0.0125.

      十六进制:

      • 0xFp2 means 15 x 2^2, or 60.0.
      • 0xFp-2 means 15 x 2^(-2), or 3.75.

      下面这些浮点型的值都是12.1875

    let decimalDouble = 12.1875
    let exponentDouble = 1.21875e1
    let hexadecimalDouble = 0xC.3p0
    

    numeric literals为了更好的阅读代码可以包含额外的格式,整型和浮点型都可以使用前缀"0"和下划线"_"

    let paddedDouble = 000123.456
    let oneMillion = 1_000_000
    let justOverOneMillion = 1_000_000.000_000_1
    
    数值类型的转换(Numeric Type Conversion)#
    • 整型的转换(Integer Conversion)
      当然,整形的存储是不能超过类型的范围的,那UInt8(0255)和Int8(-128127)为例:
    let cannotBeNegative: UInt8 = -1
    //UInt8 cannot store negative numbers, and so this will report an error.
    let tooBig: Int8 = Int8.max + 1
    //Int8 cannot store a number larger than its maximum value,
    //and so this will also report an error
    

    当两种数值不是一个类型的时候是不能进行运算的,哪怕他们都是“整型”:

    let twoThousand: UInt16 = 2_000
    let one: UInt8 = 1
    let towThousandAndOne = twoThousand + UInt16(one)
    //swift的强制转换和OC是不同的,swift是将类型放在括号外面,而将变量(常量)放在括号里面。
    
    • 整型和浮点型之间的相互转换(Integer and Floating-Point Conversion)
      在整型和浮点型之间转换一定要明确:
    let three = 3
    let pointOneFourOneFiveNine = 0.141459
    let pi = Double(three) + pointOneFourOneFiveNine
    // pi equals 3.14159, and is inferred to be of type Double
    
    类型的别称(Type Aliases)

    类型的重命名用到的是"typealias"关键字。

    typealias AudioSample = UInt16
    //correct
    let max: AudioSample = AudioSample.max
    //wrong
    let max: AudioSample = UInt16.max
    
    布尔型(Boolean)

    Swift中的布尔型与C语言和OC都不一样,为"Bool",而其值和C语言是一直的,分别为"true"和"false"。
    因为type safety的缘故,下面的代码是错误的

    let i = 1
    if i {
        //this example will not compile, and will repot an error
    }
    

    所以,这段代码应该这么写:

    let i = 1
    if i == 1 {
        //this example will compile successfully
    }
    

    因为"i == 1"的返回值是Bool,所以这段代码可以执行。

    元组(Tuples)

    元组就是一组多个值合成为一个单一的值,而这一组的多个值并不是一定要相同的类型。
    🌰:

    let http404Error = (404, "Not Found")
    //http404Error is of type (Int, String)
    

    你可以在创建一个元组的时候任意的排序类型。
    你也可以在定义一个元组的时候,将类型分离,🌰:

    let (statusCode, statusMessage) = http404Error
    print("The status code is \(statusCode)")
    //Prints "The status code is 404"
    

    如果你只需要为元组中的某个元素命名是,其他的可以用下划线(_)代替:

    let (justTheStatusCode, _) = http404Error
    print("The status code is \(justTheStatusCode)")
    // Prints "The status code is 404"
    

    你也可以通过访问元组的索引值来访问相应的元素:

    print("The status code is \(http200Status.statusCode)")
    // Prints "The status code is 200"
    print("The status message is \(http200Status.description)")
    // Prints "The status message is OK"
    

    在定义一个元组的时候,就可以为每个元素命名,这样就可以直接通过元素名称来访问:

    let http200Status = (statusCode: 200, description: "OK")
    
    print("The status code is \(http200Status.statusCode)")
    // Prints "The status code is 200"
    print("The status message is \(http200Status.description)")
    // Prints "The status message is OK"
    
    可选变量(Optionals)#

    在C语言和OC中是没有optionals的概念的,但在OC中有一个类似的类型就是NSNil。Optionals通俗点讲,就是这个值可能存在,也可能不存在。举个🌰:

    let possibleNumber = "123"
    let convertedNumber = Int(possibleNumber)
    // convertedNumber is inferred to be of type "Int?", or "optional Int"
    
    • nil
      在声明一个变量的时候可以分配一个特殊的值——nil:
    var serverResponseCode: Int? = 404
    // serverResponseCode contains an actual Int value of 404
    serverResponseCode = nil
    // serverResponseCode now contains no value
    

    在声明一个可选变量的时候不赋给初始值,默认为nil(数值类型的值同样为nil)。

    • 可选绑定(Optional Binding)
      可选绑定,如果一个可选变量的值不为nil,则将值赋给另外一个变量(常量)。可选绑定可以用在if和while的判断条件中。🌰:
    if let actualNumber = Int(possibleNumber) {
            print("\"\(possibleNumber)\" has an integer value of \(actualNumber)")
    } else {
            print("\"\(possibleNumber)\" could not be converted to an integer")
    }
    // Prints ""123" has an integer value of 123"
    

    你可以在一个if判断条件中包含多个可选绑定和"where"子句来进行判断,如果其中有任意一个可选绑定为空(nil),或者"where"的返回值为"false",整个可选绑定都会不成功:

    if let firstNumber = Int("4"), secondNumber = Int("42") where irstNumber < secondNumber {
            print("\(firstNumber) < \(secondNumber)")
    }
    // Prints "4 < 42"
    
    • 隐式解析可选类型(Implicitly Unwrapped Optional)(也不知道是不是叫这个名字)
      有些变量在声明的时候就已经有值了,如果还是每次都判断是否为空就会非常低效,所以就有了这个Implicity Unwrapped Optional类型,意思就是我声明的这个变量不为空,用感叹号表示(!)。
      下面这个🌰展示了Optionals和Implicity Unwrapped Optional的区别:
    let possibleString: String? = "An optional string."
    let forcedString: String = possibleString! // requires an exclamation mark
    let assumedString: String! = "An implicitly unwrapped optional string."
    let implicitString: String = assumedString // no need for an exclamation mark
    

    同样的,你可以判断隐式解析可选类型是否为空(nil),也可以进行可选绑定。
    🌰:

    if assumedString != nil {
        print(assumedString)
    }
    // Prints "An implicitly unwrapped optional string."
    if let definiteString = assumedString {
        print(definiteString)
    }
    // Prints "An implicitly unwrapped optional string."
    
    异常处理(Error Handling)

    当一个方法遇到错误情况,它就会抛出(throws)一个错误。而方法的调用者就会捕捉(catch)到错误信息,并及时处理。

    func canThrowAnError() throws {
        //this function may or may not throw an error
    }
    

    当一个方法可以抛出错误的时候在它声明方法名的时候要包括"throws"关键字。当你调用一个可以抛出错误的方法时,在前面用"try"关键字来修饰。
    Swift会自动将错误信息从当先这个范围传递出去,知道会遇到"catch"子句的时候才会进行处理。

    do {
        try canThrowAnError()
        //no error was thrown
    } catch {
        //an error was thrown
    }
    

    "do"状态创建了一个新的可以允许错误信息传递给一个或者多个"catch"子句的包含范围。
    🌰:

    func makeASandwich() throws {
    // ...
    }
    
    do {
        try makeASandwich()
        eatASandwich()
    } catch SandwichError.outOfCleanDishes {
        washDishes()
    } catch SandwichError.missingIngredients(let ingredients) {
        buyGroceries(ingredients)
    }
    

    上面这个🌰中,"makeASandewich()"将会在没有干净盘子的时候执行"washDishes()"。之所以"makeASandwich()"可以抛出一个错误,是因为这个方法包含了"try"表达式。如果没有错误抛出,那么"eatASandwich()"这个方法就会执行。

    • 断言(Assertions)
      在某些情况下,如果一个特定的条件不满足,那么代码就不会继续执行。在这些情况下,你可以在你的代码中设置一个断言(asserttion)来结束代码的执行或者提供一个调试值为空或者不存在的机会。

      • 用断言进行调试(Debug with Assertions)
        assertion会在runtime检查一个Boolean表达式的值是否为true。字面的意思就是,一个assertion"断言"一个表达式是否为真。如果表达式的值为true,那么代码会照常执行,如果表达式的值为false,代码执行结束,app会直接终止。
        但你在调试情况下使用assertions,可以附加一条自己的信息。在Swift标准库中,调用"assert(::file:line:)"方法,这是一个全球变量:
    let age = -3
    assert(age >= 0, "A person's age cannot be less than zero")
    //this causes the assertion to trigger, because age is not >= 0
    

    assertions的信息也可以省略。

    assert(age >= 0)
    
    • 什么时候使用断言(When to Use Assertions)
      使用assertions首先要确保表达是的值有可能为false,但是想要代码继续执行的话,值一定为true。以下几种情况适用assertions:
      • 一个整数下标索引值传到了一个自定义的下标实现,而值超出了范围(太小或太大)。
      • 给函数传入一个值,但是非法的值可能导致函数不能正常执行。
      • 一个可选值现在为nil,但是代码需要一个不为nil的值才能成功执行。

    相关文章

      网友评论

        本文标题:Swift3.0基础部分(The Basics)(二)

        本文链接:https://www.haomeiwen.com/subject/epmkjttx.html