作者:Aaron Dean,日期:2020.05.01

思维导图

控制流(Control Flow)


Swift 提供多种控制流语句。其中,条件判断使用 if 语句 、guard语句和 switch 语句 ,根据特定条件执行不同的代码分支; 循环使用 for – in 语句,while 语句和 repeat – while 语句,重复执行任务。Swift 中的 switch 语句也比 C 语言中的更加强大,case 可以匹配许多不同的模式,如间隔匹配、元组和强制转换为特定类,并且复杂的匹配条件可以通过 where 子句来表示。另外,Swift 中也有诸如 break 和 continue 之类的控制转移语句。

条件或循环变量周围的圆括号( )是可选的,但条件语句或循环语句的主体必须要有花括号{ }。比如,下面的示例代码中,score 及 studScores 周围可以不写圆括号( ),但{ }不能省,否则编译将出错。

Part1 循环


Q 1:for – in 循环

Swift提供的 for-in 循环,使得程序能够轻松地遍历数组、字典、区间、字符串和其他序列。关于 for – in 循环其实前面介绍集合类型(Collection Types )时已经使用过了。我们可以使用 for – in 循环迭代输出键值对(key-value pair)。字典是无序集,如果不使用 sorted( )方法,输出键值对的顺序将是不确定的。示例代码如下:

第一次执行的结果:

第二次执行的结果(代码未改动,你的打印结果顺序和我的不一定相同):

可以使用 ..< 来表示上限值,使用来表示包含全部范围,比如:

使用stride(from:to:by:)函数跳过某些不想要的标记,如果是闭区间的情况,使用 stride(from:through:by:) 函数。

Q 2:while 循环 & repeat – while 循环

使用 while 循环反复执行一段代码块,直到条件不满足时停止执行。如果迭代的初始值无法预知时,就用它。Swift 提供两种类型的 while 循环。

  • while 在每次循环开始时评估条件是否满足。
  • repeat-while 在每次循环结束时评估条件是否满足(循环条件在末尾)。

repeat-while 是while 的变体,使用 repeat-while 能够保证代码至少执行一次。Swift中的repeat-while循环类似于其他语言中的do-while循环。

下面的两段示例代码,前一段代码由于循环条件不满足,所以循环体中的代码未执行,n的值依旧为 2. 而后一段代码,由于循环条件在末尾,虽然循环条件不满足,但是循环体中的代码仍旧能够至少执行一次,所以 m 的值翻倍,变成了 4.

Part 2 条件判断


Q 1:如何使用 if 语句进行条件判断

if 语句适合可能结果不多的简单情况。在 if 语句里,条件必须是一个布尔表达式(Boolean expression)。若上述的代码把“score > 60 ”改成“score”,Xcode无法编译通过,因为Swift 里并没有隐含和 0进行比较的假设。错误信息提示如下:

将 if 和 let 组合使用可以处理值缺失的情况。这些值可表示为可选类型( optional)的值。可选类型分有值和没值两种情况,用 nil 表示没有值。在值后面写上一个问号 ?,表示值的类型是可选类型。if – let 是怎么处理可选值的呢?如果可选值yourName为 nil,条件就不成立,那么括号{ }中的代码将被跳过。否则,可选值 yourName 将被解包, 并被赋给 let 后面的常量 name,这样括号{ }中的代码块可以使用这个值了。

另外一种处理可选值的方法是:使用空合运算符(??)提供一个默认值。如果可选值缺失,就用默认值替代。如果将下面这段代码中的 nil 换成” Young Shaun “, 这时候由于 nickName 有值” Young Shaun “,所以就用不着默认值”Shaun Murphy”。

Q 2:如何使用 switch 语句进行条件判断 ?

switch语句更适合于具有多个可能排列的复杂条件,且在使用模式匹配帮助选择合适的代码分支来执行的情况下很有用。关于 switch 语句,需要说明的是:

  • switch语句支持任何类型的数据且支持多种比较运算,不局限于整数、相等比较。
  • 每个 case 的主体必须包含至少一条可执行语句。
  • switch 语句默认区分大小写,若想使switch 语句不区分大小写,需要将两个值组合成使用逗号分隔的复合case
  • switch 必须是完备(exhaustive)的,即在 switch 里面需要将所有的情况都考虑到。

你可以在使用 switch 语句之前先定义一个枚举(enum)类型或其他的数据结构,把有关的 case 都例举出来。当无法考虑所有情况时,可以添加 default case 来包含所有其他未明确描述的情况。如果漏了这一句,编译会给出错误提示信息:Switch must be exhaustive,即switch 必须是完备的。

Q 3: 复合 case 与值绑定

共享同一个主体(body)的多个 switch cases ,可以在 case 关键字后使用逗号对多个值进行分隔。

复合 case 还可以包括值绑定(value bindings)。switch 的 case 可以将其匹配的一个或多个值命名为临时常量或变量,以用于case 的主体。 这种行为称为值绑定,因为值绑定到案例主体中的临时常量或变量。

示例代码包括3种模式都包含距离绑定:(let x, 0)匹配x轴上的点,(0, let y)匹配y轴上的点,let(x, y)匹配不在轴上的点。

Q 4 : 元组(Tuples)

你可以使用 元组(Tuples)在同一 switch 语句中测试多个值。 可以针对不同的值或值的间隔测试元组的每个元素。 或者,使用下划线字符(_)(也称为通配符模式)来匹配任何可能的值。

下面的示例代码采用一个(x,y)点,表示为(Int,Int)类型的简单元组,并将其分类在该示例之后的图形上。

Q 5 :间隔匹配(Interval Matching)

Q 6 : Where 语句

switch 语句的 case 可以使用 where 子句检查额外的条件。

Q 7 : 控制转移语句(Control Transfer Statements)

Swift 有 5 个控制转移语句: continue、break、 fallthrough、 return 和 throw,你可以使用这些语句改变代码执行的顺序。此处仅叙述前 3 个,return 语句将在函数(Functions)中介绍,throw 语句将在错误处理部分(Propagating Errors Using Throwing Functions)介绍。

  • continue语句

让循环停止正在执行的操作,并在循环的下一次迭代开始时重新开始。 它说“我完成了当前的循环迭代”,而没有完全离开循环。

  • break语句

break 语句立即结束整个控制流语句的执行。

在循环语句中使用break时,会立即结束循环的执行,并在循环的右括号(})之后将控制权转移给代码。 不会执行循环的当前迭代中的其他代码,也不会启动循环的其他迭代。

在 switch 语句中使用时,break将使 switch 语句立即结束其执行,并将控制权转移到 switch 语句的右括号(})之后。

Q8:贯穿(Fallthrough)

在 Swift 中,整个switch语句将在第一个匹配的 switch case 完成后立即完成整个 switch 语句的执行,不需要显式的在每一个 case 后插入 break 语句以防止失败,即 No Implicit Fallthrough。这使得 Swift 可以避免错误地执行多个 switch 的情况。

尽管在Swift中不需要break,当然你也可以使用break语句来匹配和忽略特定的情况,或者在该情况完成执行之前就退出匹配的情况。

如果你确实需要向 C 语言那样的的 fallthrough 行为,则可以使用 fallthrough 关键字视情使用。 下面的示例使用 fallthrough 来创建数字的文本描述。

Q 9 :标签语句(Labeled Statements)

Swift 中循环和条件语句也是可以嵌套的。但是,循环和条件语句都可以使用break语句提前结束执行。因此,为了明确是要让break语句终止哪一条循环或条件语句,可以使用语句标签(statement label)标记循环语句或条件语句。。

Q 10 : 检查 API 的可用性(Checking API Availability)

Swift 内置了对API可用性检查的支持,可确保你不会意外使用给定部署目标上不可用的API。

编译器使用SDK中的可用性信息来验证代码中使用的所有API在项目指定的部署目标上是否可用, 尝试使用不可用的API时Swift编译时报错。

你可以在 if 或 guard 语句中使用可用性条件来有条件地执行代码块,具体取决于要使用的API在运行时(runtime)是否可用。 当编译器验证该代码块中的API可用时,将使用可用性条件中的信息。

最后一个参数*是必需的,它指定在任何其他平台上,if的主体在目标所指定的最小部署目标上执行。

在一般情况下,可用性条件采用平台名称和版本的列表。 您使用平台名称,例如iOS,macOS,watchOS和tvOS,完整列表请参阅Declaration Attributes。 除了指定主要版本号(例如iOS 8或macOS 10.10)之外,您还可以指定次要版本号(例如iOS 11.2.6和macOS 10.13.3)。


参考资料:Swift —ControlFlow

文档协议:CC-BY-4.0(共享-演绎-署名-不附加限制)