• Swift学习笔记七


    控制流

    Swift提供了和C类似的控制流表达式,包括for、while、if、switch。当然也包括break和continue这种语句来引导控制流到某个指定点的语句。

    在C的for基础上,Swift提供了更强大的for-in,遍历起来更方便。

    Swift的switch也比C中的更强大,其中的case在执行之后并不会继续执行下一个case,这样就避免了C中忘记写break时产生的逻辑错误。同时,case也能匹配更多的模式,包括间隔匹配,元组等,被匹配的值可以被赋值给变量或者常量,以便在case的执行体中使用。并且复杂的匹配条件可以在case中用where分句。

    循环语句

    for和C类似,语法如下:

    for var index = 0; index < 3; ++index {
        println("index is (index)")
    }

    注意,Swift中for后面的"初始值;条件;增量"块并不需要用括号括起来。此时,“初始值”中声明的变量(如示例中的index)只有在循环体内部才能被引用。

    for-in用于遍历数组或者范围或者字典等,比如:

    for index in 1...5 {
        println("(index) times 5 is (index * 5)")
    }

    在这种形式中,index是一个常量,它的值在每次循环的时候都被自动设定为了正确的值,在使用它之前,并不需要显示地声明这个常量,在循环结构中它已经被隐式地声明了。

    如果不需要使用这个序列中的值,那么可以用下划线来代替:

    let base = 3
    let power = 10
    var answer = 1
    for _ in 1...power {
        answer *= base
    }
    println("(base) to the power of (power) is (answer)")
    // prints "3 to the power of 10 is 59049”

    这种情况下,在每次循环时并不需要知道当前的index,只是需要确保循环体执行了指定的次数。

    用for-in遍历数组、集合、字典前面都有介绍,不再赘述。

    while也与其他语言类似,知道判定条件为假才停止循环,在不能确切知道循环次数的时候尤为有用。当然也有do-while。

    条件语句

    if语句与C语言类似,只是不需要括号来包围条件语句了。比如:

    temperatureInFahrenheit = 90
    if temperatureInFahrenheit <= 32 {
        println("It's very cold. Consider wearing a scarf.")
    } else if temperatureInFahrenheit >= 86 {
        println("It's really warm. Don't forget to wear sunscreen.")
    } else {
        println("It's not that cold. Wear a t-shirt.")
    }
    // prints "It's really warm. Don't forget to wear sunscreen.”

    switch表达式略微不同,Swift中必须使得所有case加起来能够包含所有情况,因此通常如果不用罗列所有条件则使用default来处理其他所有case都没有命中时的情况。每个case可以处理多个匹配关系。

    let someCharacter: Character = "e"
    switch someCharacter {
    case "a", "e", "i", "o", "u":
        println("(someCharacter) is a vowel")
    case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
    "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
        println("(someCharacter) is a consonant")
    default:
        println("(someCharacter) is not a vowel or a consonant")
    }
    // prints "e is a vowel”

    与C、OC中的switch相反,Swift中的switch并没有隐式顺序执行(就是在执行完一个case后如果没有break就顺序执行下一个case),在执行完一个case之后,就跳出了整个switch代码块,因此switch中break语句并不是必须的。

    在每个case的执行体中,必须至少有一个可以执行语句,比如,如下写法就是错误的:

    let anotherCharacter: Character = "a"
    switch anotherCharacter {
    case "a":
    case "A":
        println("The letter A")
    default:
        println("Not the letter A")
    }
    // this will report a compile-time error

    每个case的多项匹配条件可以用逗号分开,并且可以写在多行里。

    间隔匹配(Interval Matching)

    在switch的case中可以判断是否在包含在某个间隔,使得可以以一种接近自然语言的方式编写代码:

    let count = 3_000_000_000_000
    let countedThings = "stars in the Milky Way"
    var naturalCount: String
    switch count {
    case 0:
        naturalCount = "no"
    case 1...3:
        naturalCount = "a few"
    case 4...9:
        naturalCount = "several"
    case 10...99:
        naturalCount = "tens of"
    case 100...999:
        naturalCount = "hundreds of"
    case 1000...999_999:
        naturalCount = "thousands of"
    default:
        naturalCount = "millions and millions of"
    }
    println("There are (naturalCount) (countedThings).")
    // prints "There are millions and millions of stars in the Milky Way.”

    注意,这里...和..<两个范围(range)方法都被重载,以便返回间隔(interval),间隔可以确定它本身是否包含某个特定的值或元素,此时就可以用在switch的case中,而范围则是一系列连续的值的集合,可以在for-in循环中被遍历。

    也可以用元组在一个switch中判断多个值,元组的每个元素都可以被单独匹配某个值或者间隔,用下划线来作为占位符匹配任意值,比如:

    let somePoint = (1, 1)
    switch somePoint {
    case (0, 0):
        println("(0, 0) is at the origin")
    case (_, 0):
        println("((somePoint.0), 0) is on the x-axis")
    case (0, _):
        println("(0, (somePoint.1)) is on the y-axis")
    case (-2...2, -2...2):
        println("((somePoint.0), (somePoint.1)) is inside the box")
    default:
        println("((somePoint.0), (somePoint.1)) is outside of the box")
    }
    // prints "(1, 1) is inside the box”

    和C不一样,Swift中的switch允许多个case重复匹配某个值,如果多个case都满足匹配条件,那么最开始符合条件的case被触发,然后跳出整个switch块。

    值绑定

    一个switch的case可以在匹配条件的情况下将值临时绑定到一个变量或者常量上,然后就可以在case的执行体内部使用它。比如:

    let anotherPoint = (2, 0)
    switch anotherPoint {
    case (let x, 0):
        println("on the x-axis with an x value of (x)")
    case (0, let y):
        println("on the y-axis with a y value of (y)")
    case let (x, y):
        println("somewhere else at ((x), (y))")
    }
    // prints "on the x-axis with an x value of 2”

    注意,这里并没有default的分支,是因为最后一个分支用了两个占位符常量,整个分支集合就可以包含所有情况了。

    where

    一个switch的case可以使用where分句来判断额外的条件

    let yetAnotherPoint = (1, -1)
    switch yetAnotherPoint {
    case let (x, y) where x == y:
        println("((x), (y)) is on the line x == y")
    case let (x, y) where x == -y:
        println("((x), (y)) is on the line x == -y")
    case let (x, y):
        println("((x), (y)) is just some arbitrary point")
    }
    // prints "(1, -1) is on the line x == -y”

    这里也是最后一个case满足了所有其他情况,因而省略了default分支。

    控制转移语句

    Swift有四个控制转移语句:

    continue
    break
    fallthrough
    return

    continue语句让循环体停止正在做的事情,转而开始进行下一次循环。(注意,这里只是跳过了循环体本身,循环的其他部分仍然是执行的,比如for循环中条件变量仍然会改变)

    break语句立即终止了整个控制流的执行。它可以被用在switch块或者循环块中,当用在循环块中时,它终止整个循环的执行,并跳到循环块后面的第一条语句,此语句之后的任何循环语句不再被执行。switch中的break则终止整个switch块的执行,跳到块后的第一条语句。

    fallthrough语句是为了模拟C语言中的switch语句的行为的,Swift中的switch在命中一个case之后并不会自动执行下一个case,如果你希望它具备这个特性,就是用fallthrough语句:

    let integerToDescribe = 5
    var description = "The number (integerToDescribe) is"
    switch integerToDescribe {
    case 2, 3, 5, 7, 11, 13, 17, 19:
        description += " a prime number, and also"
        fallthrough
    default:
        description += " an integer."
    }
    println(description)
    // prints "The number 5 is a prime number, and also an integer.”

    fallthrough关键字并不会检查被它触发的顺序执行的case是否满足条件,它只是简单地将控制点从当前case转移到下个case或者default分支,就像C中一样。

    标签语句(Labeled Statements)

    循环语句和switch语句都是可以嵌套的,它们也可以互相嵌套,从而构建复杂的控制流,儿在循环体和switch中都可以是用break语句来改变控制流,这就使得复杂的控制流中,break语句究竟是针对哪个块变得比较复杂,为了解决这个问题,可以用标签显示地致命它所针对的块。类似地,如果是嵌套的循环,那么可以用同样的方式解决continue语句的问题。

    标签语句的语法是在控制流的关键字前加上标签和冒号,比如:

    let finalSquare = 25
    var board = [Int](count: finalSquare + 1, repeatedValue: 0)
    board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
    board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
    var square = 0
    var diceRoll = 0
    
    gameLoop: while square != finalSquare {
        if ++diceRoll == 7 { diceRoll = 1 }
        switch square + diceRoll {
        case finalSquare:
            break gameLoop
        case let newSquare where newSquare > finalSquare:
            continue gameLoop
        default:
            square += diceRoll
            square += board[square]
        }
    }
    println("Game over!")”

    如果没有是用标签语句,那么break和continue这种语句只会作用于它外层最接近它的块。

  • 相关阅读:
    IOS7 UI设计的十大准则
    IOS8-人机界面指南
    Android应用切换皮肤功能实现
    Android 打造自己的个性化应用(五):仿墨迹天气实现续--> 使用Ant实现zip/tar的压缩与解压
    Android 打造自己的个性化应用(四):仿墨迹天气实现-->自定义扩展名的zip格式的皮肤
    Android 打造自己的个性化应用(三):应用程序的插件化
    Android 打造自己的个性化应用(二):应用程序内置资源实现换肤功能
    Android 打造自己的个性化应用(一):应用程序换肤主流方式的分析与概述
    Android防止内存泄漏以及MAT的使用
    Android内存泄漏监测(MAT)及解决办法
  • 原文地址:https://www.cnblogs.com/dson/p/4561521.html
Copyright © 2020-2023  润新知