Swift提供了和许多语言相通的流程控制结构, 包括循环语句: for和while, 选择语句: if, guard和switch, 跳转语句: break, continue. 与Objective - C相同的, Swift也有for - in循环用来更简单的进行遍历序列. Swift的switch语句比许多语言更加强大, Swift中的每一个case无需写break, 避免了其他语言漏写break发生贯穿的情况. case还可以匹配更多的类型, 这包括区间, 元组和特定类型的描述. switch的case语句中匹配的值可以是由case内部临时的常量或者变量决定, 也可以由where分句描述复杂的匹配条件.
Swift提供了两种for循环形式以来多次执行一系列语句:
1. for - in循环对一个集合里每个元素执行一系列语句
2. for循环, 用来重复执行一系列语句直到达成特定条件, 一般通过在每次循环完成后增加计数的形式来实现.
可以使用for - in循环来遍历一个集合里面的所有元素, 例如由数字表示的区间, 数组中的元素, 字符串中的字符等.
下面的例子是使用for - in循环输出一个99乘法表
例子中用来进行遍历的元素是一组使用闭区间操作符" ... "表示的从 1
到 9 的数字. i是一个每次循环遍历开始时被自动赋值的常量, 在这种情况下, i在使用前不需要声明, 只需要将它包含在循环的声明中就可以对其进行隐式声明, 无需使用let/var关键字声明.
如果不需要知道区间序列内每一项的值, 可以使用下划线" _ "替代变量名来忽略对值的访问
遍历字典时, 字典的每项 元素会以(key, value)元组的形式返回, 可以在for - in循环中使用显式的常量名称来解读(key, value)元组.
除了for - in循环, Swift提供使用条件判断和递增(递减)的标准C样式的for循环. 和C语言一样, " ; "将循环的定义分为3个部分, 不同的是Swift不需要使用" ( ) "将"initialization; condition; increment"括起来.
for循环执行流程如下:
1. 循环首次启动时, 初始化表达式(initialization)被调用一次, 用来初始化循环所需的所有常量和变量.
2. 条件表达式(condition)被调用, 如果表达式调用结果为false, 循环结束, 继续执行for循环关闭" } "之后的代码. 如果表达式调用结果为true, 则会执行" { } "内部的代码.
3. 执行所有语句之后, 执行递增(递减)表达式(increment), 通常会增加或减少计数器的值, 或者根据语句输出来修改某一个初始化的变量. 当递增(递减)表达式运行完成后, 重复执行第2步, 条件表达式会再次执行.
下面的例子是使用for循环来输出一个99乘法表
while循环运行一系列语句直到条件变成false. 这类循环适合使用在第一次迭代前迭代次数未知的情况下.
Swift提供了两种while循环形式:
1. while循环, 每次在循环开始时计算条件是否符合.
2. repeat - while循环, 每次在循环结束时计算条件是否符合.
while循环从计算单一条件开始, 如果条件为true, 会重复运行一系列语句, 直到条件变为false
下面的例子是使用while循环来输出一个99乘法表
while循环的另外一种形式是repeat-while循环, 它和其他语言中的do-while循环是类似的. 它与while循环的区别是: 在判断循环条件之前, 先执行一次循环的代码块, 然后重复循环直到条件为false.
下面的例子是使用repeat - while循环来输出一个99乘法表
Swift 提供两种类型的选择语句: if语句和switch语句. 通常, 当条件较为简单且可能的情况很少时, 使用if语句. 而switch语句更适用于条件较复杂, 可能情况较多且需要用到模式匹配.
if语句最简单的形式就是只包含一个条件, 当且仅当该条件为true时, 才执行相关代码.
当然, if语句允许二选一, 也就是当条件为false时, 执行else语句.
也可以把多个if语句链接在一起, 像下面这样
switch语句会尝试把某个值与若干个模式进行匹配, 根据第一个匹配成功的模式, switch语句会执行对应的代码. 当有可能的情况较多时, 通常用switch来语句替换if语句.
switch语句都由多个case构成, 每一个 case 都是代码执行的一条分支, 这与if语句类似。与之不同的是, switch语句会决定哪一条分支应该被执行.
switch语句必须是完备的. 这就是说, 每一个可能的值都必须至少有一个 case 分支与之对应.在某些不可能涵盖所有值的情况下, 你可以使用默认default分支满足该要求,这个默认分支必须在switch语句的最后面.
与 C 语言和 Objective-C 中的switch语句不同, 在 Swift 中, 当匹配的case分支中的代码执行完毕后, 程序会终止switch语句, 而不会继续执行下一个case分支. 这也就是说, 不需要在case分支中显式地使用break语句. 这使得switch语句更安全易用, 也避免了因忘记写break语句而产生的错误.
case分支的模式也可以是一个值的区间.
下面的例子展示了如何使用区间匹配来输出任意数字对应的自然语言格式
可以使用元组在同一个switch语句中测试多个值, 元组中的元素可以是值, 可以是区间, 也可以使用" _ "来匹配所有可能的值.
swift允许多个case匹配同一个值, 但如果存在多个匹配, 只会执行第一个被匹配的case分支.
case分支的模式允许将匹配的值绑定到一个临时的常量或变量, 这些常量或变量在该case分支里就可以被引用了--这种行为被称为值绑定.
case分支的模式可以使用where语句来判断额外的条件
控制转移语句改变你代码的执行顺序, 通过它可以实现代码的跳转.
continue语句告诉一个循环体立刻停止本次循环迭代, 重新开始下次循环迭代, 但是并不会离开整个循环体. 在一个带有条件和递增(递减)的for循环体中, 调用continue语句后, 迭代增量仍然会被计算求值. 循环体继续继续像往常一样工作, 仅仅只是循环体中的执行代码会被跳过.
break语句会立刻结束整个控制流的执行. 当你想要更早的结束一个switch代码块或者一个循环体时, 你都可以使用break语句.
当在一个循环体中使用break时, 会立刻中断该循环体的执行, 然后跳转到表示循环体结束的大括号" { " 后的第一行代码. 不会再有本次循环迭代的代码被执行, 也不会再有下次的循环迭代产生.
当在一个switch代码块中使用break时, 会立即中断该switch代码块的执行, 并且跳转到表示 switch代码块结束的大括号" } "后的第一行代码.
这种特性可以被用来匹配或者忽略一个或多个分支. 因为Swift的switch需要包含所有的分支而且不允许有为空的分支, 有时为了使意图更明显, 需要特意匹配或者忽略某个分支, 可以在该分支内写上break语句. 当那个分支被匹配到时, 分支内的break语句立即结束switch代码块.
注 : 当一个switch分支仅仅包含注释时, 会在编译时报错. 因为注释不是代码语句而且也不能让switch分支达到被忽略的效果.
Swift中的switch不会从上一个case分支落入到下一个case分支中. 相反, 只要第一个匹配到的case分支完成了它需要执行的语句, 整个switch代码块就完成了它的执行. 相比之下, C语言要求显式的插入break语句到每个switch分支的末尾来阻止自动落入到下一个case分支中. Swift 的这种避免默认落入到下一个分支中的特性意味着它的switch功能要比C语言的更加清晰和可预测, 可以避免无意识地执行多个case分支从而引发的错误.
如果确实需要C语言风格的贯穿的特性, 可以在每个需要该特性的case分支中使用fallthrough关键字.
下面的例子使用fallthrough来创建一个数字的描述语句
在Swift中, 可以在循环体和switch代码块中嵌套循环体和switch代码块来创造复杂的控制流结构. 然而, 循环体和switch代码块两者都可以使用break语句来提前结束整个方法体. 因此,显式地指明break语句想要终止的是哪个循环体或者switch代码块会很有用. 类似地, 如果你有许多嵌套的循环体, 显式指明continue语句想要影响哪一个循环体也会非常有用.
为了实现这个目的, 可以使用标签来标记一个循环体或者switch代码块, 当使用break或者continue时, 带上这个标签, 可以控制该标签代表对象的中断或者执行.
产生一个带标签的语句是通过在该语句的关键词的同一行前面放置一个标签, 并且该标签后面还需带着一个冒号.
像if语句一样, guard的执行取决于一个表达式的布尔值. 我们可以使用guard语句来要求条件必须为真时以执行guard语句后的代码. 不同于if语句, 一个guard语句总是有一个else分句, 如果条件不为真则执行else分句中的代码.
如果guard语句的条件被满足, 则在保护语句的封闭大括号结束后继续执行代码. 任何使用了可选绑定作为条件的一部分并被分配了值的变量或常量对于剩下的保护语句出现的代码段是可用的.
如果条件不被满足, 在else分支上的代码就会被执行. 这个分支必须转移控制以退出guard语句出现的代码段. 它可以用控制转移语句如return, break, continue或throw做这件事, 或者调用一个不返回的方法或函数.
相比于可以实现同样功能的if语句, 按需使用guard语句会提升我们代码的可靠性. 它可以使你的代码连贯的被执行而不需要将它包在else块中, 它可以使你处理违反要求的代码使其接近要求.
Swift有检查API可用性的内置支持, 这可以确保我们不会不小心地使用对于当前部署目标不可用的 API. 编译器使用 SDK 中的可用信息来验证我们的代码中使用的所有 API 在项目指定的部署目标上是否可用. 如果我们尝试使用一个不可用的API, Swift会在编译时报错.