diff --git a/source/chapter2/18_Error_Handling.md b/source/chapter2/18_Error_Handling.md index b43bb4fd..0fa9ff1c 100755 --- a/source/chapter2/18_Error_Handling.md +++ b/source/chapter2/18_Error_Handling.md @@ -53,7 +53,8 @@ Swift 中有`4`种处理错误的方式。你可以把函数抛出的错误传 > 注意 > Swift 中的错误处理和其他语言中用`try`,`catch`和`throw`进行异常处理很像。和其他语言中(包括 Objective-C )的异常处理不同的是,Swift 中的错误处理并不涉及解除调用栈,这是一个计算代价高昂的过程。就此而言,`throw`语句的性能特性是可以和`return`语句相媲美的。 -###用 throwing 函数传递错误 + +### 用 throwing 函数传递错误 为了表示一个函数、方法或构造器可以抛出错误,在函数声明的参数列表之后加上`throws`关键字。一个标有`throws`关键字的函数被称作*throwing 函数*。如果这个函数指明了返回值类型,`throws`关键词需要写在箭头(`->`)的前面。 diff --git a/source/chapter3/10_Statements.md b/source/chapter3/10_Statements.md index abd6a674..a3a8f356 100755 --- a/source/chapter3/10_Statements.md +++ b/source/chapter3/10_Statements.md @@ -4,7 +4,7 @@ > 1.0 > 翻译:[coverxit](https://github.com/coverxit) -> 校对:[numbbbbb](https://github.com/numbbbbb), [coverxit](https://github.com/coverxit), [stanzhai](https://github.com/stanzhai), +> 校对:[numbbbbb](https://github.com/numbbbbb), [coverxit](https://github.com/coverxit), [stanzhai](https://github.com/stanzhai) > 2.0 > 翻译+校对:[littledogboy](https://github.com/littledogboy) @@ -12,579 +12,676 @@ 本页包含内容: - [循环语句](#loop_statements) + - [For 语句](#for_statements) + - [For-In 语句](#for-in_statements) + - [While 语句](#while_statements) + - [Repeat-While 语句](#repeat-while_statements) - [分支语句](#branch_statements) -- [带标签的语句](#labeled_statement) -- [控制传递语句](#control_transfer_statements) + - [If 语句](#if_statements) + - [Guard 语句](#guard_statements) + - [Switch 语句](#switch_statements) +- [带标签的语句](#labeled_statements) +- [控制转移语句](#control_transfer_statements) + - [Break 语句](#break_statement) + - [Continue 语句](#continue_statement) + - [Fallthrough 语句](#fallthrough_statements) + - [Return 语句](#return_statements) + - [Available 语句](#availability_statements) + - [Throw 语句](#throw_statements) +- [Defer 语句](#defer_statements) +- [Do 语句](#do_statements) +- [编译器控制语句](#compiler_control_statements) + - [编译配置语句](#build_config_statements) + - [源代码控制语句](#line_control_statements) -在 Swift 中,有三种类型的语句:简单语句、编译控制语句和控制流语句。简单语句是最常见的,用于构造表达式或者声明。编译控制语句允许程序改变编译器的行为以及包含构建配置和源代码控制语句。 +在 Swift 中,有三种类型的语句:简单语句、编译器控制语句和控制流语句。简单语句是最常见的,用于构造表达式或者声明。编译器控制语句允许程序改变编译器的行为,包含编译配置语句和线路控制语句。 -控制流语句则用于控制程序执行的流程,Swift 中有几种类型的控制流语句:循环语句、分支语句和控制传递语句。循环语句用于重复执行代码块;分支语句用于执行满足特定条件的代码块;控制传递语句则用于修改代码的执行顺序。另外,Swift 提供了 `do` 语句来引入范围以及捕获和处理错误,还提供了 `defer` 语句在退出当前范围之前执行清理操作。 +控制流语句则用于控制程序执行的流程,Swift 中有多种类型的控制流语句:循环语句、分支语句和控制转移语句。循环语句用于重复执行代码块;分支语句用于执行满足特定条件的代码块;控制转移语句则用于改变代码的执行顺序。另外,Swift 提供了 `do` 语句,用于构建局部作用域,还用于错误的捕获和处理;还提供了 `defer` 语句,用于退出当前作用域之前执行清理操作。 -是否将分号(`;`)添加到语句的结尾处是可选的。但若要在同一行内写多条独立语句,请务必使用分号。 +是否将分号(`;`)添加到语句的末尾是可选的。但若要在同一行内写多条独立语句,则必须使用分号。 > 语句语法 -> *语句* → [*表达式*](../chapter3/04_Expressions.html#expression) **;** _可选_ -> *语句* → [*声明*](../chapter3/05_Declarations.html#declaration) **;** _可选_ -> *语句* → [*循环语句*](../chapter3/10_Statements.html#loop_statement) **;** _可选_ -> *语句* → [*分支语句*](../chapter3/10_Statements.html#branch_statement) **;** _可选_ -> *语句* → [*标记语句(Labeled Statement)*](../chapter3/10_Statements.html#labeled_statement) -> *语句* → [*控制转移语句*](../chapter3/10_Statements.html#control_transfer_statement) **;** _可选_ -> *语句* → [*XXX语句*](../chapter3/10_Statements.html#control_transfer_statement) **;** _可选_ -> *多条语句(Statements)* → [*语句*](../chapter3/10_Statements.html#statement) [*多条语句(Statements)*](../chapter3/10_Statements.html#statements) _可选_ + +> *语句* → [*表达式*](04_Expressions.md#expression) **;**可选 +> *语句* → [*声明*](05_Declarations.md#declaration) **;**可选 +> *语句* → [*循环语句*](#loop-statement) **;**可选 +> *语句* → [*分支语句*](#branch-statement) **;**可选 +> *语句* → [*带标签的语句*](#labeled-statement) **;**可选 +> *语句* → [*控制转移语句*](#control-transfer-statement) **;**可选 +> *语句* → [*defer 语句*](#defer-statement) **;**可选 +> *语句* → [*do 语句*](#do-statement) **:**可选 +> *语句* → [*编译器控制语句*](#compiler-control-statement) + +> *多条语句* → [*语句*](#statement) [*多条语句*](#statements)可选 ## 循环语句 -取决于特定的循环条件,循环语句允许重复执行代码块。Swift 提供四种类型的循环语句:`for`语句、`for-in`语句、`while`语句和`do-while`语句。 +循环语句会根据特定的循环条件来重复执行代码块。Swift 提供四种类型的循环语句:`for` 语句、`for-in` 语句、`while` 语句和 `repeat-while` 语句。 -通过`break`语句和`continue`语句可以改变循环语句的控制流。有关这两条语句,详情参见 [Break 语句](#break_statement)和 [Continue 语句](#continue_statement)。 +通过 `break` 语句和 `continue` 语句可以改变循环语句的控制流。有关这两条语句,详情参见 [Break 语句](#break_statement) 和 [Continue 语句](#continue_statement)。 > 循环语句语法 -> *循环语句* → [*for语句*](../chapter3/10_Statements.html#for_statement) -> *循环语句* → [*for-in语句*](../chapter3/10_Statements.html#for_in_statement) -> *循环语句* → [*while语句*](../chapter3/10_Statements.html#wheetatype类型ile_statement) -> *循环语句* → [*do-while语句*](../chapter3/10_Statements.html#do_while_statement) + +> *循环语句* → [*for 语句*](#for-statement) +> *循环语句* → [*for-in 语句*](#for-in-statement) +> *循环语句* → [*while 语句*](#while-statement) +> *循环语句* → [*repeat-while 语句*](#repeat-while-statement) ### For 语句 -`for`语句只有在循环条件为真时重复执行代码块,此时计数器递增。 +`for` 语句只有在循环条件为真时重复执行代码块,同时计数器递增。 -`for`语句的形式如下: +`for` 语句的形式如下: -> for `initialzation`; `condition`; `increment` { -> `statements` -> } +```swift +for 初始化; 条件; 增量 { + 语句 +} +``` -*initialzation*、*condition* 和 *increment* 之间的分号,以及包围循环体 *statements* 的大括号都是不可省略的。 +初始化、条件和增量语句之间必须以分号相隔,循环体中的语句必须以花括号包裹。 -`for`语句的执行流程如下: +`for` 语句的执行流程如下: -1. *initialzation* *循环变量* 只会被执行一次,通常用于声明和初始化在接下来的循环中需要使用的变量。 -2. 判断 *condition* 循环条件: - 如果为`true`,*statements* *循环体* 将会被执行,然后转到第3步。如果为`false`,*statements* 和 *increment* *循环增量* 都不会被执行,`for`至此执行完毕。 -3. 计算 *increment* 表达式,然后转到第2步。 +1. 初始化只会被执行一次,通常用于声明和初始化在接下来的循环中需要使用的变量。 +2. 判断条件的值。如果为 `true`,循环体中的语句将会被执行,然后转到第 3 步;如果为 `false`,循环体中的语句以及增量语句都不会被执行,`for` 语句至此执行完毕。 +3. 执行增量语句,然后重复第 2 步。 -在 *initialzation* 中定义的变量仅在`for`循环的作用域内有效。*condition* 表达式的值的类型必须遵循`BooleanType `协议。 +在初始化语句中定义的变量仅在 `for` 循环的作用域内有效。 -> For 循环语法 -> *for语句* → **for** [*for初始条件*](../chapter3/10_Statements.html#for_init) _可选_ **;** [*表达式*](../chapter3/04_Expressions.html#expression) _可选_ **;** [*表达式*](../chapter3/04_Expressions.html#expression) _可选_ [*代码块*](../chapter3/05_Declarations.html#code_block) -> *for语句* → **for** **(** [*for初始条件*](../chapter3/10_Statements.html#for_init) _可选_ **;** [*表达式*](../chapter3/04_Expressions.html#expression) _可选_ **;** [*表达式*](../chapter3/04_Expressions.html#expression) _可选_ **)** [*代码块*](../chapter3/05_Declarations.html#code_block) -> *for初始条件* → [*变量声明*](../chapter3/05_Declarations.html#variable_declaration) | [*表达式列表*](../chapter3/04_Expressions.html#expression_list) +条件的结果必须符合 `BooleanType` 协议。 +> for 语句语法 + +> *for 语句* → **for** [*for初始条件*](#for-init)可选 **;** [*表达式*](04_Expressions.md#expression)可选 **;** [*表达式*](04_Expressions.md#expression)可选 [*代码块*](05_Declarations.md#code-block) +> *for语句* → **for** **(** [*for初始条件*](#for-init)可选 **;** [*表达式*](04_Expressions.md#expression)可选 **;** [*表达式*](04_Expressions.md#expression)可选 **)** [*代码块*](05_Declarations.md#code-block) + +> *for 初始条件* → [*变量声明*](05_Declarations.md#variable-declaration) | [*表达式列表*](04_Expressions.md#expression-list) ### For-In 语句 -`for-in`语句允许在重复执行代码块的同时,迭代集合(或遵循`Sequence`协议的任意类型)中的每一项。 +`for-in` 语句会为集合(或符合 `Sequence` 协议的任意类型)中的每一项执行一次代码块。 -`for-in`语句的形式如下: +`for-in` 语句的形式如下: -> for `item` in `collection` { -> `statements` -> } +```swift +for 项 in 集合 { + 循环体语句 +} +``` -`for-in`语句在循环开始前会调用 *collection* 表达式的`generate`方法来获取一个生成器类型(这是一个遵循`Generator`协议的类型)的值。接下来循环开始,调用 *collection* 表达式的`next`方法。如果其返回值不是`None`,它将会被赋给 *item*,然后执行 *statements*,执行完毕后回到循环开始处;否则,将不会赋值给 *item* 也不会执行 *statements*,`for-in`至此执行完毕。 - -> For-In 循环语法 -> *for-in语句* → **for** [*模式*](../chapter3/07_Patterns.html#pattern) **in** [*表达式*](../chapter3/04_Expressions.html#expression) [*代码块*](../chapter3/05_Declarations.html#code_block) +`for-in` 语句在循环开始前会调用集合表达式的 `generate()` 方法来获取一个符合 `Generator` 协议的类型的值。接下来循环开始,反复调用该值的 `next()` 方法。如果其返回值不是 `None`,它将会被赋给“项”,然后执行循环体语句,执行完毕后回到循环开始处,继续重复这一过程;否则,既不会赋值也不会执行循环体语句,`for-in` 语句至此执行完毕。 +> for-in 语句语法 + +> *for-in 语句* → **for** **case**可选 [*模式*](07_Patterns.md#pattern) **in** [*表达式*](04_Expressions.md#expression) [*where子句*](#where-clause)可选 [*代码块*](05_Declarations.md#code-block) ### While 语句 -`while`语句当循环条件为真时,允许重复执行代码块。 +只要循环条件为真,`while` 语句就会重复执行代码块。 -`while`语句的形式如下: +`while` 语句的形式如下: -> while `condition` { -> `statements` -> } +```swift +while 条件 { + 语句 +} +``` -`while`语句的执行流程如下: +`while` 语句的执行流程如下: -1. 计算 *condition* 表达式: - 如果为真`true`,转到第2步。如果为`false`,`while`至此执行完毕。 -2. 执行 *statements* ,然后转到第1步。 +1. 判断条件的值。如果为 `true`,转到第 2 步;如果为 `false`,`while` 语句至此执行完毕。 +2. 执行循环体中的语句,然后重复第 1 步。 -由于 *condition* 的值在 *statements* 执行前就已计算出,因此`while`语句中的 *statements* 可能会被执行若干次,也可能不会被执行。 +由于会在执行循环体中的语句前判断条件的值,因此循环体中的语句可能会被执行若干次,也可能一次也不会被执行。 -*condition* 表达式的值的类型必须遵循`BooleanType `协议。同时,*condition* 表达式也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。 +条件的结果必须符合 `BooleanType` 协议。另外,条件语句也可以使用可选绑定,请参阅 [可选绑定](../chapter2/01_The_Basics.md#optional_binding)。 -> While 循环语法 -> *while语句* → **while** [*while条件*](../chapter3/10_Statements.html#while_condition) [*代码块*](../chapter3/05_Declarations.html#code_block) -> *条件* → [*表达式*](../chapter3/04_Expressions.html#expression) | [*声明*](../chapter3/05_Declarations.html#declaration) -> *条件* → [*表达式*](../chapter3/04_Expressions.html#expression) -> *条件* → [*表达式*](../chapter3/04_Expressions.html#expression) | [*条件列表*](TODO) -> *条件* → [*可用条件*](../chapter3/10_Statement.html#availability) [*表达式*](../chapter3/04_Expressions.html#expression) -> *条件列表* → [*条件条件*](TODO) [*条件列表*](TODO) -> *条件* → [*可用条件*](../chapter3/10_Statement.html#availability) [可选绑定条件](../chapter2/01_The_Basics.html#optional_binding) -> *case条件* → **case** [*模式*](../chapter3/07_Patterns.html#pattern) [构造器](TODO) [where](DOTO) -> *可选绑定条件* → [可选绑定头](TODO) [持续可选绑定](TODO) [持续可选绑定列表](TODO) -> *可选绑定头* → **let** [*模式*](../chapter3/07_Patterns.html#pattern) [构造器](TODO) **var** [*模式*](../chapter3/07_Patterns.html#pattern) [构造器](TODO) -> *可持续绑定列表* → [*模式*](../chapter3/07_Patterns.html#pattern) | [构造器](TODO) [可选绑定头](TODO) -> +> while 语句语法 + +> *while 语句* → **while** [*条件子句*](#condition-clause) [*代码块*](05_Declarations.md#code-block) + +> *条件子句* → [*表达式*](04_Expressions.md#expression) +> *条件子句* → [*表达式*](04_Expressions.md#expression) **,** [*条件列表*](#condition-list) +> *条件子句* → [*条件列表*](#condition-list) +> *条件子句* → [*可用性条件*](#availability-condition) **,** [*表达式*](04_Expressions.md#expression) - + +> *条件列表* → [*条件*](#condition) | [*条件*](#condition) **,** [*条件列表*](#condition-list) + +> *条件* → [*可用性条件*](#availability-condition) | [*case条件*](#case-condition) | [*可选绑定条件*](#optional-binding-condition) + +> *case 条件* → **case** [*模式*](07_Patterns.md#pattern) [*构造器*](05_Declarations.md#initializer) [where子句](#where-clause)可选 + + +> *可选绑定条件* → [*可选绑定头*](#optional-binding-head) [*可选绑定附加列表*](#optional-binding-continuation-list)可选 [*where子句*](#where-clause)可选 + +> *可选绑定头* → **let** [*模式*](07_Patterns.md#pattern) [*构造器*](05_Declarations.md#initializer) | **var** [*模式*](07_Patterns.md#pattern) [*构造器*](05_Declarations.md#initializer) + +> *可选绑定附加部分列表* → [*可选绑定附加部分*](#optional-binding-continuation) | [*可选绑定附加部分*](#optional-binding-continuation) **,** [*可选绑定附加部分列表*](#optional-binding-continuation-list) + +> *可选绑定附加部分* → [*模式*](07_Patterns.md#pattern) [*构造器*](05_Declarations.md#initializer) | [*可选绑定头*](#optional-binding-head) + + ### Repeat-While 语句 -`repeat-while`语句允许代码块被执行一次或多次。 +`repeat-while` 语句至少执行一次代码块,之后只要循环条件为真,就会重复执行代码块。 -`repeat-while`语句的形式如下: +`repeat-while` 语句的形式如下: -> repeat { -> `statements` -> } while `condition` +```swift +repeat { + 语句 +} while 条件 +``` -`repeat-while`语句的执行流程如下: +`repeat-while` 语句的执行流程如下: -1. 执行 *statements*,然后转到第2步。 -2. 计算 *condition* 表达式: - 如果为`true`,转到第1步。如果为`false`,`repeat-while`至此执行完毕。 +1. 执行循环体中的语句,然后转到第 2 步。 +2. 判断条件的值。如果为 `true`,重复第 1 步;如果为 `false`,`repeat-while` 语句至此执行完毕。 -由于 *condition* 表达式的值是在 *statements* 执行后才计算出,因此`repeat-while`语句中的 *statements* 至少会被执行一次。 +由于条件的值是在循环体中的语句执行后才进行判断,因此循环体中的语句至少会被执行一次。 -*condition* 表达式的值的类型必须遵循`BooleanType `协议。同时,*condition* 表达式也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。 +条件的结果必须符合 `BooleanType` 协议。另外,条件语句也可以使用可选绑定,请参阅 [可选绑定](../chapter2/01_The_Basics.md#optional_binding)。 -> Repeat-While 循环语法 -> * repeat-while语句* → **repeat** [*代码块*](../chapter3/05_Declarations.html#code_block) **while** [*while条件*](../chapter3/10_Statements.html#while_condition) +> repeat-while 语句语法 + +> *repeat-while 语句* → **repeat** [*代码块*](05_Declarations.md#code-block) **while** [*表达式*](04_Expressions.md#expression) ## 分支语句 -取决于一个或者多个条件的值,分支语句允许程序执行指定部分的代码。显然,分支语句中条件的值将会决定如何分支以及执行哪一块代码。Swift 提供两种类型的分支语句:`if`语句和`switch`语句。 +分支语句会根据一个或者多个条件来执行指定部分的代码。分支语句中的条件将会决定程序如何分支以及执行哪部分代码。Swift 提供两种类型的分支语句:`if` 语句和 `switch` 语句。 -`switch`语句中的控制流可以用`break`语句修改,详情请见[Break 语句](#break_statement)。 +`if` 语句和 `switch` 语句中的控制流可以用 `break` 语句改变,请参阅 [Break 语句](#break_statement)。 > 分支语句语法 -> *分支语句* → [*if语句*](../chapter3/10_Statements.html#if_statement) -> *分支语句* → [*switch语句*](../chapter3/10_Statements.html#switch_statement) - + +> *分支语句* → [*if 语句*](#if-statement) +> *分支语句* → [*guard 语句*](#guard-statement) +> *分支语句* → [*switch 语句*](#switch-statement) ### If 语句 -取决于一个或多个条件的值,`if`语句将决定执行哪一块代码。 +`if` 语句会根据一个或多个条件来决定执行哪一块代码。 -`if`语句有两种标准形式,在这两种形式里都必须有大括号。 +`if` 语句有两种基本形式,无论哪种形式,都必须有花括号。 第一种形式是当且仅当条件为真时执行代码,像下面这样: -> if `condition` { -> `statements` -> } +```swift +if 条件 { + 语句 +} +``` -第二种形式是在第一种形式的基础上添加 *else 语句*,当只有一个 else 语句时,像下面这样: +第二种形式是在第一种形式的基础上添加 `else` 语句,当只有一个 `else` 语句时,像下面这样: -> if `condition` { -> `statements to execute if condition is true` -> } else { -> `statements to execute if condition is false` -> } +```swift +if 条件 { + 若条件为真则执行这部分语句 +} else { + 若条件为假则执行这部分语句 +} +``` -同时,else 语句也可包含`if`语句,从而形成一条链来测试更多的条件,像下面这样: +`else` 语句也可包含 `if` 语句,从而形成一条链来测试更多的条件,像下面这样: -> if `condition 1` { -> `statements to execute if condition 1 is true` -> } else if `condition 2` { -> `statements to execute if condition 2 is true` -> } -> else { -> `statements to execute if both conditions are false` -> } +```swift +if 条件1 { + 若条件1为真则执行这部分语句 +} else if 条件2 { + 若条件2为真则执行这部分语句 +} else { + 若前两个条件均为假则执行这部分语句 +} +``` -`if`语句中条件的值的类型必须遵循`LogicValue`协议。同时,条件也可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。 - -> If语句语法 -> *if语句* → **if** [*if条件*](../chapter3/10_Statements.html#if_condition) [*代码块*](../chapter3/05_Declarations.html#code_block) [*else(Clause)*](../chapter3/10_Statements.html#else_clause) _可选_ -> *if条件* → [*表达式*](../chapter3/04_Expressions.html#expression) | [*声明*](../chapter3/05_Declarations.html#declaration) -> *else(Clause)* → **else** [*代码块*](../chapter3/05_Declarations.html#code_block) | **else** [*if语句*](../chapter3/10_Statements.html#if_statement) +`if` 语句中条件的结果必须符合 `BooleanType` 协议。另外,条件语句也可以使用可选绑定,请参阅 [可选绑定](../chapter2/01_The_Basics.md#optional_binding)。 +> if 语句语法 + +> *if 语句* → **if** [*条件子句*](#condition-clause) [*代码块*](05_Declarations.md#code-block) [*else子句*](#else-clause)可选 + +> *else 子句* → **else** [*代码块*](05_Declarations.md#code-block) | **else** [*if语句*](#if-statement) ### Guard 语句 -`guard` 语句用来转移程序控制出其作用域,如果一个或者多个条件不成立。 - `guard` 语句的格式如下: - > guard `condition` else { - `statements` - >} +如果一个或者多个条件不成立,可用 `guard` 语句用来退出当前作用域。 + +`guard` 语句的格式如下: + +```swift +guard 条件 else { + 语句 +} +``` - `guard`语句中条件值的类型必须遵循`LogicValue`协议。且条件可以使用可选绑定,详情参见[可选绑定](../chapter2/01_The_Basics.html#optional_binding)。 +`guard` 语句中条件的结果必须符合 `BooleanType` 协议,而且条件语句可以使用可选绑定,请参阅 [可选绑定](../chapter2/01_The_Basics.md#optional_binding)。 - 在`guard`语句中声明的常量或者变量,可用范围从声明开始到作用域结束,常量和变量的值从可选绑定声明中分配。 +在 `guard` 语句中进行可选绑定的常量或者变量,其可用范围从声明开始直到作用域结束。 - `guard`语句需要有`else`子句,并且必须调用被`noreturn`属性标记的函数,或者使用下面的语句把程序执行转移到guard语句的作用域外。 +`guard` 语句必须有 `else` 子句,而且必须在该子句中调用标记 `noreturn` 特性的函数,或者使用下面的语句退出当前作用域: * `return` * `break` * `continue` * `throw` -执行转移语句详情参见[控制传递语句](TODO) +关于控制转移语句,请参阅 [控制转移语句](#control_transfer_statements)。 +> guard 语句语法 + +> *guard 语句* → **guard** [*条件子句*](#condition-clause) **else** [*代码块*](05_Declarations.md#code-block) ### Switch 语句 -取决于`switch`语句的*控制表达式(control expression)*,`switch`语句将决定执行哪一块代码。 +`switch` 语句会根据控制表达式的值来决定执行哪部分代码。 -`switch`语句的形式如下: +`switch` 语句的形式如下: -> switch `control expression` { -> case `pattern 1`: -> `statements` -> case `pattern 2` where `condition`: -> `statements` -> case `pattern 3` where `condition`, -> `pattern 4` where `condition`: -> `statements` -> default: -> `statements` -> } +```swift +switch 控制表达式 { +case 模式1: + 语句 +case 模式2 where 条件: + 语句 +case 模式3 where 条件, 模式4 where 条件: + 语句 +default: + 语句 +} +``` -`switch`语句的*控制表达式(control expression)*会首先被计算,然后与每一个 case 的模式(pattern)进行匹配。如果匹配成功,程序将会执行对应的 case 分支里的 *statements*。另外,每一个 case 分支都不能为空,也就是说在每一个 case 分支中至少有一条语句。如果你不想在匹配到的 case 分支中执行代码,只需在该分支里写一条`break`语句即可。 +`switch` 语句会先计算控制表达式的值,然后与每一个 `case` 的模式进行匹配。如果匹配成功,程序将会执行对应的 `case` 中的语句。另外,每一个 `case` 都不能为空,也就是说在每一个 `case` 中必须至少有一条语句。如果你不想在匹配到的 `case` 中执行代码,只需在该 `case` 中写一条 `break` 语句即可。 -可以用作控制表达式的值是十分灵活的,除了标量类型(scalar types,如`Int`、`Character`)外,你可以使用任何类型的值,包括浮点数、字符串、元组、自定义类的实例和可选(optional)类型,甚至是枚举类型中的成员值和指定的范围(range)等。关于在`switch`语句中使用这些类型,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的 [Switch](../chapter2/05_Control_Flow.html#switch)。 +可以用作控制表达式的值是十分灵活的。除了标量类型外,如 `Int`、`Character`,你可以使用任何类型的值,包括浮点数、字符串、元组、自定义类型的实例和可选类型,甚至是指定的 `Range` 或枚举类型中的成员值。关于如何在 `switch` 语句中使用这些类型,请参阅 [控制流](../chapter2/05_Control_Flow.md) 一章中的 [Switch](../chapter2/05_Control_Flow.html#switch)。 -你可以在模式后面添加一个起保护作用的表达式(guard expression)。*起保护作用的表达式*是这样构成的:关键字`where`后面跟着一个作为额外测试条件的表达式。因此,当且仅当*控制表达式*匹配一个*case*的某个模式且起保护作用的表达式为真时,对应 case 分支中的 *statements* 才会被执行。在下面的例子中,*控制表达式*只会匹配含两个相等元素的元组,如`(1, 1)`: +每个 `case` 的模式后面可以有一个 `where` 子句。`where` 子句由 `where` 关键字紧跟一个提供额外测试条件的表达式组成。因此,当且仅当控制表达式匹配一个 `case` 的模式且 `where` 子句的表达式为真时,`case` 中的语句才会被执行。在下面的例子中,控制表达式只会匹配包含两个相等元素的元组,例如 `(1, 1)`: ```swift case let (x, y) where x == y: ``` -正如上面这个例子,也可以在模式中使用`let`(或`var`)语句来绑定常量(或变量)。这些常量(或变量)可以在其对应的起保护作用的表达式和其对应的*case*块里的代码中引用。但是,如果 case 中有多个模式匹配控制表达式,那么这些模式都不能绑定常量(或变量)。 +正如上面这个例子,也可以在模式中使用 `let`(或 `var`)语句来绑定常量(或变量)。这些常量(或变量)可以在对应的 `where` 子句以及 `case` 中的代码中使用。但是,如果一个 `case` 中含有多个模式,那么这些模式都不能绑定常量(或变量)。 -`switch`语句也可以包含默认(`default`)分支,只有其它 case 分支都无法匹配控制表达式时,默认分支中的代码才会被执行。一个`switch`语句只能有一个默认分支,而且必须在`switch`语句的最后面。 +`switch` 语句也可以包含默认分支,使用 `default` 关键字表示。只有所有 `case` 都无法匹配控制表达式时,默认分支中的代码才会被执行。一个 `switch` 语句只能有一个默认分支,而且必须在 `switch` 语句的最后面。 -尽管模式匹配操作实际的执行顺序,特别是模式的计算顺序是不可知的,但是 Swift 规定`switch`语句中的模式匹配的顺序和书写源代码的顺序保持一致。因此,当多个模式含有相同的值且能够匹配控制表达式时,程序只会执行源代码中第一个匹配的 case 分支中的代码。 +`switch` 语句中 `case` 的匹配顺序和源代码中的书写顺序保持一致。因此,当多个模式都能匹配控制表达式时,只有第一个匹配的 `case` 中的代码会被执行。 -#### Switch 语句必须是完备的 +#### Switch 语句必须是详尽的 -在 Swift 中,`switch`语句中控制表达式的每一个可能的值都必须至少有一个 case 分支与之对应。在某些情况下(例如,表达式的类型是`Int`),你可以使用默认块满足该要求。 +在 Swift 中,`switch` 语句中控制表达式的每一个可能的值都必须至少有一个 `case` 与之对应。在某些无法面面俱到的情况下(例如,表达式的类型是 `Int`),你可以使用 `default` 分支满足该要求。 -#### 不存在隐式的贯穿(fall through) +#### 不存在隐式落空 -当匹配的 case 分支中的代码执行完毕后,程序会终止`switch`语句,而不会继续执行下一个 case 分支。这就意味着,如果你想执行下一个 case 分支,需要显式地在你需要的 case 分支里使用`fallthrough`语句。关于`fallthrough`语句的更多信息,详情参见 [Fallthrough 语句](#fallthrough_statement)。 +当匹配到的 `case` 中的代码执行完毕后,`switch` 语句会直接退出,而不会继续执行下一个 `case` 。这就意味着,如果你想执行下一个 `case`,需要显式地在当前 `case` 中使用 `fallthrough` 语句。关于 `fallthrough` 语句的更多信息,请参阅 [Fallthrough 语句](#fallthrough_statements)。 -> Switch语句语法 -> *switch语句* → **switch** [*表达式*](../chapter3/04_Expressions.html#expression) **{** [*SwitchCase列表*](../chapter3/10_Statements.html#switch_cases) _可选_ **}** -> *SwitchCase列表* → [*SwitchCase*](../chapter3/10_Statements.html#switch_case) [*SwitchCase列表*](../chapter3/10_Statements.html#switch_cases) _可选_ -> *SwitchCase* → [*case标签*](../chapter3/10_Statements.html#case_label) [*多条语句(Statements)*](../chapter3/10_Statements.html#statements) | [*default标签*](../chapter3/10_Statements.html#default_label) [*多条语句(Statements)*](../chapter3/10_Statements.html#statements) -> *SwitchCase* → [*case标签*](../chapter3/10_Statements.html#case_label) **;** | [*default标签*](../chapter3/10_Statements.html#default_label) **;** -> *case标签* → **case** [*case项列表*](../chapter3/10_Statements.html#case_item_list) **:** -> *case项列表* → [*模式*](../chapter3/07_Patterns.html#pattern) [*guard-clause*](../chapter3/10_Statements.html#guard_clause) _可选_ | [*模式*](../chapter3/07_Patterns.html#pattern) [*guard-clause*](../chapter3/10_Statements.html#guard_clause) _可选_ **,** [*case项列表*](../chapter3/10_Statements.html#case_item_list) -> *default标签* → **default** **:** -> *where-clause* → **where** [*guard-expression*](../chapter3/10_Statements.html#guard) -> *where-expression* → [*表达式*](../chapter3/04_Expressions.html#expression) +> switch 语句语法 + + +> *switch 语句* → **switch** [*表达式*](04_Expressions.md#expression) **{** [*switch-case列表*](#switch-cases)可选 **}** + +> *switch case 列表* → [*switch-case*](#switch-case) [*switch-case列表*](#switch-cases)可选 + +> *switch case* → [*case标签*](#case-label) [*多条语句*](#statements) | [*default标签*](#default-label) [*多条语句*](#statements) + + +> *case 标签* → **case** [*case项列表*](#case-item-list) **:** + +> *case 项列表* → [*模式*](07_Patterns.md#pattern) [*where子句*](#where-clause)可选 | [*模式*](07_Patterns.md#pattern) [*where子句*](#where-clause)可选 **,** [*case项列表*](#case-item-list) + +> *default 标签* → **default** **:** + + +> *where-clause* → **where** [*where表达式*](#where-expression) + +> *where-expression* → [*表达式*](04_Expressions.md#expression) - ## 带标签的语句 -你可以在循环语句或`switch`语句前面加上*标签*,它由标签名和紧随其后的冒号(:)组成。在`break`和`continue`后面跟上标签名可以显式地在循环语句或`switch`语句中更改控制流,把控制权传递给指定标签标记的语句。关于这两条语句用法,详情参见 [Break 语句](#break_statement)和 [Continue 语句](#continue_statement)。 +你可以在循环语句或 `switch` 语句前面加上标签,它由标签名和紧随其后的冒号(`:`)组成。在 `break` 和 `continue` 后面跟上标签名可以显式地在循环语句或 `switch` 语句中改变相应的控制流。关于这两条语句用法,请参阅 [Break 语句](#break_statement) 和 [Continue 语句](#continue_statement)。 -标签的作用域是该标签所标记的语句之后的所有语句。你可以不使用带标签的语句,但只要使用它,标签名就必唯一。 +标签的作用域在该标签所标记的语句内。你可以不使用带标签的语句,但只要使用它,在作用域内需保证标签名唯一。 -关于使用带标签的语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的[带标签的语句](../chapter2/05_Control_Flow.html#labeled_statements)。 +关于使用带标签的语句的例子,请参阅 [控制流](../chapter2/05_Control_Flow.md) 一章中的 [带标签的语句](../chapter2/05_Control_Flow.md#labeled_statements)。 -> 标记语句语法 -> *标记语句(Labeled Statement)* → [*语句标签*](../chapter3/10_Statements.html#statement_label) [*循环语句*](../chapter3/10_Statements.html#loop_statement) | [*语句标签*](../chapter3/10_Statements.html#statement_label) [*switch语句*](../chapter3/10_Statements.html#switch_statement) -> *语句标签* → [*标签名称*](../chapter3/10_Statements.html#label_name) **:** -> *标签名称* → [*标识符*](../chapter3/02_Lexical_Structure.html#identifier) +> 带标签的语句语法 + +> *带标签的语句* → [*语句标签*](#statement-label) [*循环语句*](#loop-statement) | [*语句标签*](#statement-label) [*if语句*](#if-statement) | [*语句标签*](#statement-label) [*switch语句*](#switch-statement) + +> *语句标签* → [*标签名称*](#label-name) **:** + +> *标签名称* → [*标识符*](02_Lexical_Structure.md#identifier) -## 控制传递语句 +## 控制转移语句 -通过无条件地把控制权从一片代码传递到另一片代码,控制传递语句能够改变代码执行的顺序。Swift 提供四种类型的控制传递语句:`break`语句、`continue`语句、`fallthrough`语句和`return`语句。 +控制转移语句能够无条件地把控制权从一片代码转移到另一片代码,从而改变代码执行的顺序。Swift 提供五种类型的控制转移语句:`break` 语句、`continue` 语句、`fallthrough` 语句、`return` 语句和 `throw` 语句。 -> 控制传递语句(Control Transfer Statement) 语法 -> *控制传递语句* → [*break语句*](../chapter3/10_Statements.html#break_statement) -> *控制传递语句* → [*continue语句*](../chapter3/10_Statements.html#continue_statement) -> *控制传递语句* → [*fallthrough语句*](../chapter3/10_Statements.html#fallthrough_statement) -> *控制传递语句* → [*return语句*](../chapter3/10_Statements.html#return_statement) -> *控制传递语句* → [*throw语句*](../chapter3/10_Statements.html#throw_statement) +> 控制转移语句语法 + +> *控制转移语句* → [*break 语句*](#break-statement) +> *控制转移语句* → [*continue 语句*](#continue-statement) +> *控制转移语句* → [*fallthrough 语句*](#fallthrough-statement) +> *控制转移语句* → [*return 语句*](#return-statement) +> *控制转移语句* → [*throw 语句*](#throw-statement) - + ### Break 语句 -`break`语句用于终止循环或`switch`语句的执行。使用`break`语句时,可以只写`break`这个关键词,也可以在`break`后面跟上标签名(label name),像下面这样: +`break` 语句用于终止循环语句或 `switch` 语句的执行。使用 `break` 语句时,可以只写 `break` 这个关键词,也可以在 `break` 后面跟上标签名,像下面这样: > break -> break `label name` +> break `标签名` -当`break`语句后面带标签名时,可用于终止由这个标签标记的循环或`switch`语句的执行。 +当 `break` 语句后面带标签名时,可用于终止由这个标签标记的循环语句或 `switch` 语句的执行。 -而当只写`break`时,则会终止`switch`语句或上下文中包含`break`语句的最内层循环的执行。 +而只写 `break` 时,则会终止 `switch` 语句或包含 `break` 语句的最内层循环的执行。 -在这两种情况下,控制权都会被传递给循环或`switch`语句外面的第一行语句。 +在这两种情况下,控制权都会被传递给循环语句或 `switch` 语句后面的第一行语句。 -关于使用`break`语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的 [Break](../chapter2/05_Control_Flow.html#break) 和[带标签的语句](../chapter2/05_Control_Flow.html#labeled_statements)。 +关于使用 `break` 语句的例子,请参阅 [控制流](../chapter2/05_Control_Flow.md) 一章的 [Break](../chapter2/05_Control_Flow.md#break) 和 [带标签的语句](../chapter2/05_Control_Flow.md#labeled_statements)。 -> Break 语句语法 -> *break语句* → **break** [*标签名称*](../chapter3/10_Statements.html#label_name) _可选_ +> break 语句语法 + +> *break 语句* → **break** [*标签名称*](#label-name)可选 - + ### Continue 语句 -`continue`语句用于终止循环中当前迭代的执行,但不会终止该循环的执行。使用`continue`语句时,可以只写`continue`这个关键词,也可以在`continue`后面跟上标签名(label name),像下面这样: +`continue` 语句用于终止循环中当前迭代的执行,但不会终止该循环的执行。使用 `continue` 语句时,可以只写 `continue` 这个关键词,也可以在 `continue` 后面跟上标签名,像下面这样: > continue -> continue `label name` +> continue `标签名` -当`continue`语句后面带标签名时,可用于终止由这个标签标记的循环中当前迭代的执行。 +当 `continue` 语句后面带标签名时,可用于终止由这个标签标记的循环中当前迭代的执行。 -而当只写`break`时,可用于终止上下文中包含`continue`语句的最内层循环中当前迭代的执行。 +而当只写 `continue` 时,可用于终止上下文中包含 `continue` 语句的最内层循环中当前迭代的执行。 在这两种情况下,控制权都会被传递给循环外面的第一行语句。 -在`for`语句中,`continue`语句执行后,*increment* 表达式还是会被计算,这是因为每次循环体执行完毕后 *increment* 表达式都会被计算。 +在 `for` 语句中,`continue` 语句执行后,增量表达式还是会被计算,这是因为每次循环体执行完毕后,增量表达式都会被计算。 -关于使用`continue`语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的 [Continue](../chapter2/05_Control_Flow.html#continue) 和[带标签的语句](../chapter2/05_Control_Flow.html#labeled_statements)。 +关于使用 `continue` 语句的例子,请参阅 [控制流](../chapter2/05_Control_Flow.md) 一章的 [Continue](../chapter2/05_Control_Flow.md#continue) 和 [带标签的语句](../chapter2/05_Control_Flow.md#labeled_statements)。 -> Continue 语句语法 -> *continue语句* → **continue** [*标签名称*](../chapter3/10_Statements.html#label_name) _可选_ +> continue 语句语法 + +> *continue 语句* → **continue** [*标签名称*](#label-name)可选 ### Fallthrough 语句 -`fallthrough`语句用于在`switch`语句中传递控制权。`fallthrough`语句会把控制权从`switch`语句中的一个 case 传递给下一个 case 。这种传递是无条件的,即使下一个 case 的模式与`switch`语句的控制表达式的值不匹配。 +`fallthrough` 语句用于在 `switch` 语句中转移控制权。`fallthrough` 语句会把控制权从 `switch` 语句中的一个 `case` 转移到下一个 `case`。这种控制权转移是无条件的,即使下一个 `case` 的模式与 `switch` 语句的控制表达式的值不匹配。 -`fallthrough`语句可出现在`switch`语句中的任意 case 里,但不能出现在最后一个 case 分支中。同时,`fallthrough`语句也不能把控制权传递给使用了可选绑定的 case 分支。 +`fallthrough` 语句可出现在 `switch` 语句中的任意 `case` 中,但不能出现在最后一个 `case` 中。同时,`fallthrough` 语句也不能把控制权转移到使用了可选绑定的 `case`。 -关于在`switch`语句中使用`fallthrough`语句的例子,详情参见[控制流](../chapter2/05_Control_Flow.html)一章的[控制传递语句](../chapter2/05_Control_Flow.html#control_transfer_statements)。 +关于在 `switch` 语句中使用 `fallthrough` 语句的例子,请参阅 [控制流](../chapter2/05_Control_Flow.md) 一章的 [控制转移语句](../chapter2/05_Control_Flow.md#control_transfer_statements)。 -> Fallthrough 语句语法 -> *fallthrough语句* → **fallthrough** +> fallthrough 语句语法 + +> *fallthrough 语句* → **fallthrough** ### Return 语句 -`return`语句用于在函数或方法的实现中将控制权传递给调用者,接着程序将会从调用者的位置继续向下执行。 +`return` 语句用于在函数或方法的实现中将控制权转移给调用者,接着程序将会从调用者的位置继续向下执行。 -使用`return`语句时,可以只写`return`这个关键词,也可以在`return`后面跟上表达式,像下面这样: +使用 `return` 语句时,可以只写 `return` 这个关键词,也可以在 `return` 后面跟上表达式,像下面这样: > return -> return `expression` +> return `表达式` -当`return`语句后面带表达式时,表达式的值将会返回给调用者。如果表达式值的类型与调用者期望的类型不匹配,Swift 则会在返回表达式的值之前将表达式值的类型转换为调用者期望的类型。 +当 `return` 语句后面带表达式时,表达式的值将会返回给调用者。如果表达式的值的类型与函数或者方法声明的返回类型不匹配,Swift 则会在返回表达式的值之前将表达式的值的类型转换为返回类型。 -而当只写`return`时,仅仅是将控制权从该函数或方法传递给调用者,而不返回一个值。(这就是说,该函数或方法的返回类型为`Void`或`()`) +> 注意 +> 正如 [可失败构造器](05_Declarations.md#failable_initializers) 中所描述的,`return nil` 在可失败构造器中用于表明构造失败。 -> Return 语句语法 -> *return语句* → **return** [*表达式*](../chapter3/04_Expressions.html#expression) _可选_ +而只写 `return` 时,仅仅是将控制权从该函数或方法转移给调用者,而不返回一个值(也就是说,函数或方法的返回类型为 `Void` 或者说 `()`)。 + +> return 语句语法 + +> *return 语句* → **return** [*表达式*](04_Expressions.html#expression)可选 -### Availability 语句 +### Available 语句 -可用性条件,被当做`if` ,`while` 语句的条件,并且 `guard` 语句在运行时会基于特定的语法格式查询接口的可用性。 +可用性条件可作为 `if`,`while`,`guard` 语句的条件,可以在运行时基于特定的平台参数来查询 API 的可用性。 -avaliability 语句的形式如下: -> if #available(`platform name version`,` ...`, *) { -> `statements to execute if the APIs are available` -> } else { -> `fallback statements to execute if the APIs are unavailable` -> } +可用性条件的形式如下: -可用性条件执行一个代码块时,取决于在运行时想要使用的接口是否可用。 -当编译器检查到代码块中的接口是可用的,则从可用性条件中获取相应信息。 +```swift +if #available(平台名称 版本, ..., *) { + 如果 API 可用,则执行这部分语句 +} else { + 如果 API 不可用,则执行这部分语句 +} +``` -可用性条件使用逗号分隔平台名称和版本列表。使用`iOS`,`OSX`,以及`watchOS`为平台名称,包括相应的版本号。*参数是必需的。在任何平台上代码块主体都被可用性条件保护起来,由满足最低部署条件的目标设备运行。 +使用可用性条件来执行一个代码块时,取决于使用的接口在运行时是否可用。编译器会根据可用性条件提供的信息以及运行时的平台来决定是否执行相应的代码块。 + +可用性条件使用一系列逗号分隔的平台名称和版本。使用 `iOS`,`OSX`,以及 `watchOS` 等作为平台名称,并写上相应的版本号。`*` 参数是必须写的,用于处理未来的潜在平台。可用性条件确保了运行时的平台不低于条件中指定的平台版本时才执行代码块。 -与布尔类型条件不同,不能用逻辑运算符 **&&** 和 **||** 合并可用性条件。 +与布尔类型的条件不同,不能用逻辑运算符 `&&` 和 `||` 合并可用性条件。 > 可用性条件语法 -> *可用性条件* → **#available** ( [availability-arguments­](TODO) ) -> *可用性条件* → [availability-argument­](TODO) | [availability-argument](TODO)­ ,­ [availability-arguments­](TODO) -> *可用性条件* → [平台名称](TODO) [版本号](TODO) -> *可用性条件* → **\*** -> *平台名称* → **iOS** | **iOSApplicationExtension** -> *平台名称* → **OSX** | **OSXApplicationExtension­** -> *平台名称* → **watchOS** -> *版本号* → [十进制数字](TODO) -> *版本号* → [十进制数字](TODO) **.** [十进制数字](TODO) -> *版本号* → [十进制数字](TODO) **.** [十进制数字](TODO) **.** [十进制数字](TODO) - + +> *可用性条件* → **#available** **(** [*可用性参数列表*](#availability-arguments) **)** + +> *可用性参数列表* → [*可用性参数*](#availability-argument) | [*可用性参数*](#availability-argument) **,** [*可用性参数列表*](#availability-arguments) + +> *可用性参数* → [平台名称](#platform-name) [平台版本](#platform-version) +> *可用性条件* → __*__ + + +> *平台名称* → **iOS** | **iOSApplicationExtension** +> *平台名称* → **OSX** | **OSXApplicationExtension** +> *平台名称* → **watchOS** + +> *平台版本* → [十进制数字](02_Lexical_Structure.md#decimal-digits) +> *平台版本* → [十进制数字](02_Lexical_Structure.md#decimal-digits) **.** [十进制数字](02_Lexical_Structure.md#decimal-digits) +> *平台版本* → [十进制数字](02_Lexical_Structure.md#decimal-digits) **.** [十进制数字](02_Lexical_Structure.md#decimal-digits) **.** [十进制数字](02_Lexical_Structure.md#decimal-digits) + ### Throw 语句 -`throw`语句出现在抛出函数或者抛出方法体内,或者类型被`throws`关键字标记的表达式体内。 + +`throw` 语句出现在抛出函数或者抛出方法体内,或者类型被 `throws` 关键字标记的闭包表达式体内。 -`throw`语句使程序结束执行当前的作用域,并在封闭作用域中传播错误。抛出的错误会一直传播,直到被`do`语句的`catch`子句处理掉。 +`throw` 语句使程序在当前作用域结束执行,并向外围作用域传播错误。抛出的错误会一直传播,直到被 `do` 语句的 `catch` 子句处理掉。 -`throw`语句由`throw`关键字 跟一个表达式组成 ,如下所示。 +`throw` 语句由 `throw` 关键字紧跟一个表达式组成,如下所示: -> throw `expression` +> throw `表达式` -表达式值的类型必须遵循 `LogicValue`协议 +表达式的结果必须符合 `ErrorType` 协议。 -关于如何使用`throw`语句的例子,详情参见[错误处理](TODO)一章的[抛出错误](TODO)。 +关于如何使用 `throw` 语句的例子,请参阅 [错误处理](../chapter2/18_Error_Handling.md) 一章的 [用 throwing 函数传递错误](../chapter2/18_Error_Handling.md#propagating_errors_using_throwing_functions)。 > throw 语句语法 -> *抛出语句* → **throw** *[表达式­](TODO)* + +> *throw 语句* → **throw** [*表达式*](04_Expressions.md#expression) -### Defer 语句 +## Defer 语句 - `defer` 语句用于转移程序控制出延迟语句作用域之前执行代码。 - -在 `defer` 语句中的语句无论程序控制如何转移都会执行。这意味着 `defer` 语句可以被使用在以下这些情况,像手动得执行资源管理,关闭文件描述,或者即使抛出了错误也需要去实现执行一些动作。 +`defer` 语句用于在退出当前作用域之前执行代码。 -如果多个 `defer` 语句出现在同一范围内,那么它们执行的顺序与出现的顺序相反。给定作用域中的第一个`defer` 语句,会在最后执行,这意味着最后执行的延迟语句中的语句涉及的资源可以被其他 `defer`语句清理掉。 +`defer` 语句形式如下: -> 1 func f( ) { -> 2 defer { print("First") } -> 3 defer { print("Second") } -> 4 defer { print("Third") } -> 5 } -> 6 f() -> 7 // prints "Third" -> 8 // prints "Second" -> 9 // prints "First" +```swift +defer { + 语句 +} +``` +在 `defer` 语句中的语句无论程序控制如何转移都会执行。这意味着 `defer` 语句可以被使用在以下这些情况,例如关闭文件描述,或者即使抛出了错误也需要执行的一些动作。 -`defer` 语句中的语句无法转移程序控制出延迟语句。 +如果多个 `defer` 语句出现在同一作用域内,那么它们执行的顺序与出现的顺序相反。给定作用域中的第一个 `defer` 语句,会在最后执行,这意味着最后执行的 `defer` 语句中涉及的资源可以被其他 `defer` 语句清理掉。 + +```swift +func f() { + defer { print("First") } + defer { print("Second") } + defer { print("Third") } +} +f() +// 打印 “Third” +// 打印 “Second” +// 打印 “First” +``` + +`defer` 语句中的语句无法将控制权转移到 `defer` 语句外部。 > defer 语句语法 -> *延迟语句* → **defer** *[代码块](TODO)* - + +> *延迟语句* → **defer** [*代码块*](05_Declarations.md#code-block) -### Do 语句 +## Do 语句 -`do` 语句用于引入一个新的作用域,该作用域中可以含有一个或多个`catch`子句,catch子句中定义了一些匹配错误情况的模式。`do` 语句作用域内定义的常量和变量,只能在do语句作用域内访问。 +`do` 语句用于引入一个新的作用域,该作用域中可以含有一个或多个 `catch` 子句,`catch` 子句中定义了一些匹配错误条件的模式。`do` 语句作用域内定义的常量和变量,只能在 `do` 语句作用域内使用。 -swift 中的 do 语句与C 中限定代码块界限的大括号 ({})很相似,并且在程序运行的时候并不会造成系统开销。 +Swift 中的 `do` 语句与 C 中限定代码块界限的大括号(`{}`)很相似,并且在程序运行的时候并不会造成系统开销。 -> do { -> try `expression` -> `statements` -> } catch `pattern 1` { - `statements` -> } catch `pattern 2` where condition { - `statements` -> } +`do` 语句的形式如下: -如同`switch`语句,编译器会判断`catch`子句是否被遗漏。如果catch没有被遗漏,则认为错误被处理。否则,错误会自动传播出包含作用域,被一个封闭的`catch`语句或抛出函数处理掉,包含函数必须以`throws`关键字声明。 +```swift +do { + try 表达式 + 语句 +} catch 模式1 { + 语句 +} catch 模式2 where 条件 { + 语句 +} +``` -为了确保错误已经被处理,使用一个匹配所有错误的`catch`子句,如通配符模式(_)。如果一个`catch`子句不指定一种模式,`catch`子句会匹配和约束任何局部变量命名的`error`。有关在`catch`子句中使用模式的更多信息,详见[模式](TODO)。 +如同 `switch` 语句,编译器会判断 `catch` 子句是否有遗漏。如果 `catch` 子句没有遗漏,则认为错误被处理。否则,错误会自动传播到外围作用域,被一个 `catch` 语句处理掉或者继续向外抛出,抛出函数必须以 `throws` 关键字声明。 -关于在一些`catch`子句中如何使用` do`语句的例子,详情参见[错误处理](TODO)一章的[抛出错误](TODO)。 +为了确保错误已经被处理,可以让 `catch` 子句使用匹配所有错误的模式,如通配符模式(`_`)。如果一个 `catch` 子句不指定一种具体模式,`catch` 子句会匹配任何错误,并绑定到名为 `error` 的局部变量。有关在 `catch` 子句中使用模式的更多信息,请参阅 [模式](07_Patterns.md)。 -> do 语句语法 → **do** *[*代码块*](../chapter3/05_Declarations.html#code_block) [catch](TODO)* -> catch → *[catch子句](TODO) [catch子句](TODO)* -> catch → **catch** *[*模式*](../chapter3/07_Patterns.html#pattern)** *可选的* [*where*]() *可选的* [*代码块*](../chapter3/05_Declarations.html#code_block) +关于如何在 `do` 语句中使用一些 `catch` 子句的例子,请参阅 [处理错误](../chapter2/18_Error_Handling.md#handling_errors)。 + +> do 语句语法 + +> *do 语句* → **do** [*代码块*](05_Declarations.md#code-block) [*多条 catch子句*](#catch-clauses)可选 + +> *多条 catch 子句* → [*catch子句*](#catch-clause) [*多条 catch子句*](#catch-clauses)可选 + +> *catch 子句* → **catch** [*模式*](07_Patterns.md#pattern)可选 [*where子句*](#where-clause)可选 [*代码块*](05_Declarations.md#code-block) -### 编译控制语句 +## 编译器控制语句 -编译控制语句允许程序改变编译器的行为。Swift 有两种编译控制语句:构建配置语句和源代码控制语句。 +编译器控制语句允许程序改变编译器的行为。Swift 有两种编译器控制语句:编译配置语句和线路控制语句。 -> 编译控制语句语法 -> *编译控制语句* → [*构建配置语句*](../chapter3/04_Expressions.html#build_config_statements) -> *编译控制语句* → [*源代码控制语句*](../chapter3/04_Expressions.html#line_control_statements) +> 编译器控制语句语法 + +> *编译器控制语句* → [*编译配置语句*](#build-config-statement) +> *编译器控制语句* → [*线路控制语句*](#line-control-statement) -#### 构建配置语句 +### 编译配置语句 -构建配置语句可以根据一个或多个配置项来有条件的编译代码。 +编译配置语句可以根据一个或多个配置来有条件地编译代码。 -每一个构建配置语句都以 `#if` 开始, `#endif` 结束。如下是一个简单的构建配置语句: +每一个编译配置语句都以 `#if` 开始,`#endif` 结束。如下是一个简单的编译配置语句: -``` -#if build configuration -statements +```swift +#if 编译配置项 + 语句 #endif ``` -和 `if` 语句的条件不同,构建配置的条件是在编译时进行判断的。它的结果是:只有构建配置在编译时判断为 `true` 的情况下语句才会被编译和执行。 +和 `if` 语句的条件不同,编译配置的条件是在编译时进行判断的。只有编译配置在编译时判断为 `true` 的情况下,相应的语句才会被编译和执行。 -*构建配置* 可以是 `true` 和 `false` 的常量,也可以是使用 `-D` 命令行标志的标识符,或者是下列表格中的任意一个平台测试方法。 +编译配置可以是 `true` 和 `false` 的字面量,也可以是使用 `-D` 命令行标志的标识符,或者是下列表格中的任意一个平台测试函数。 - | 方法 | 可用参数 | - | --- | - | - | os() | OSX, iOS, watchOS, tvOS | - | arch() | i386, x86_64, arm, arm64 | - +| 函数 | 可用参数 | +| --- | --- | +| `os()` | `OSX`, `iOS`, `watchOS`, `tvOS` | +| `arch()` | `i386`, `x86_64`, `arm`, `arm64` | > 注意 -> `arch(arm)` 构建配置在 ARM 64位设备上不会返回 `true`。如果代码的构建目标是 32 位的 iOS 模拟器,`arch(i386)` 构建配置返回 `true`。 +> `arch(arm)` 编译配置在 ARM 64位设备上不会返回 `true`。如果代码在 32 位的 iOS 模拟器上编译,`arch(i386)` 编译配置返回 `true`。 -你可以使用逻辑操作符 `&&`、`||` 和 `!` 来连接构建配置,还可以使用圆括号来进行分组。 +你可以使用逻辑操作符 `&&`、`||` 和 `!` 来组合多个编译配置,还可以使用圆括号来进行分组。 -就像 `if` 语句一样,你可以使用 `#elseif` 分句来添加任意多个条件分支来测试不同的构建配置。你也可以使用 `#else` 分句来添加最终的条件分支。包含多个分支的构建配置语句例子如下: +就像 `if` 语句一样,你可以使用 `#elseif` 子句来添加任意多个条件分支来测试不同的编译配置。你也可以使用 `#else` 子句来添加最终的条件分支。包含多个分支的编译配置语句例子如下: -``` -#if build configuration 1 -statements to compile if build configuration 1 is true -#elseif build configuration 2 -statements to compile if build configuration 2 is true +```swift +#if 编译配置1 + 如果编译配置1成立则执行这部分代码 +#elseif 编译配置2 + 如果编译配置2成立则执行这部分代码 #else -statements to compile if both build configurations are false + 如果编译配置均不成立则执行这部分代码 #endif ``` -> 注意 -> 即使没有被编译,构建配置语句中的每一个分句仍然会被解析。 +> 注意 +> 即使没有被编译,编译配置中的语句仍然会被解析。 ---- -> 构建配置语句语法 -> 单个构建配置语句 → #if­ 多个构建配置语句(可选) 多个构建配置 `elseif` 分句(可选)­ 单个构建配置 `else` 分句(可选)­#endif­ -> 多个构建配置 `elseif` 分句 → 单个构建配置 `elseif`­ 分句 多个构建配置 `elseif` 分句(可选) -> 单个构建配置 `elseif`­ 分句 → #elseif­ 多个构建配置语句(可选) -> 单个构建配置 `else` 分句 → #else­ 语句(可选) -> 构建配置 → 平台测试方法 -> 构建配置 → 标识符 -> 构建配置 → boolean 常量 -> 构建配置 → (­构建配置­)­ -> 构建配置 → !­ 构建配置­ -> 构建配置 → 构建配置 &&­ 构建配置­ -> 构建配置 → 构建配置 ­||­ 构建配置­ -> 平台测试方法 → os­(­操作系统)­ -> 平台测试方法 → arch­(­架构)­ -> 操作系统 → OSX­ iOS­ watchOS­ tvOS­ -> 架构 → i386­ x86_64­ arm­ arm64­ + +> 编译配置语句语法 + + +> *单个编译配置语句* → **#if** [*编译配置*](#build-configuration) [*语句*](#statements)可选 [*多个编译配置elseif子句*](#build-configuration-elseif-clauses)可选 **-** [*单个编译配置else子句*](#build-configuration-else-clause)可选 **#endif** + +> *多个编译配置 elseif 子句* → [*单个编译配置elseif子句*](#build-configuration-elseif-clause) [*多个编译配置elseif子句*](build-configuration-elseif-clauses)可选 + +> *单个编译配置 elseif 子句* → **#elseif** [*编译配置*](#build-configuration) [*语句*](#statements)可选 + +> *单个编译配置 else 子句* → **#else** [*语句*](#statements)可选 + + +> *编译配置* → [*平台测试函数*](#platform-testing-function) +> *编译配置* → [*标识符*](02_Lexical_Structure.md#identifier) +> *编译配置* → [*布尔值字面量*](02_Lexical_Structure.md#boolean-literal) +> *编译配置* → **(** [*编译配置*](#build-configuration) **)** +> *编译配置* → **!** [*编译配置*](#build-configuration) +> *编译配置* → [*编译配置*](#build-configuration) **&&** [*编译配置*](#build-configuration) +> *编译配置* → [*编译配置*](#build-configuration) **||** [*编译配置*](#build-configuration) + + +> *平台测试函数* → **os** **(** [*操作系统*](#operating-system) **)** +> *平台测试函数* → **arch** **(** [*架构*](#architecture) **)** + +> *操作系统* → **OSX** | **iOS** | **watchOS** | **tvOS** + +> *架构* → **i386** | **x86_64** | **arm** | **arm64** -#### 源代码控制语句 +### 线路控制语句 -源代码控制语句用来给被编译源代码指定一个与原始行号和文件名不同的行号和文件名。使用源代码控制语句可以改变 Swift 使用源代码的位置,以便进行分析和测试。 +线路控制语句用来为被编译的源代码指定一个与原始行号和文件名不同的行号和文件名。使用线路控制语句可以改变源代码的位置,以便进行分析和调试。 -源代码的控制语句的例子如下: +线路控制语句形式如下: -``` -#line line number filename -``` +> \#line `行号` `文件名` -源代码控制语句改变了常量表达式 `__LINE__` 和 `__FILE__` 的值,以一行源代码开头,然后跟着源代码控制语句。`line number` 改变了 `__LINE__` 的值,它是一个大于 0 的常量。`filename` 改变了 `__FILE__` 的值,它是一个字符串常量。 +线路控制语句会改变之后的字面量表达式 `__LINE__` 和 `__FILE__` 的值。`行号` 是一个大于 0 的整形字面量,会改变 `__LINE__` 的值。`文件名` 是一个字符串字面量,会改变 `__FILE__` 的值。 -你可以通过写一句不指定 `line number` 和 `filename` 的源代码控制语句来吧源代码的位置回退到初始的行号和文件。 +你可以通过 `#line` 语句,即不指定行号和文件名,来将源代码的位置重置回默认的行号和文件名。 -源代码控制语句必须出现在源代码的那一行,而且不能是源代码文件的最后一行。 - -> 源代码控制语句 - -> 源代码控制语句 → #line­ -> 源代码控制语句 → #line­ line-number­ file-name­ -> line-number → 大于 0 的十进制数 -> file-name → 字符串常量 - - - - - - - - - - - - - - - - - +线路控制语句必须独占一行,而且不能是源代码文件的最后一行。 +> 线路控制语句语法 + +> *线路控制语句* → **#line** +> *线路控制语句* → **#line** [*行号*](#line-number) [*文件名*](#file-name) + +> *行号* → 大于 0 的十进制整数 + +> *文件名* → [*静态字符串字面量*](02_Lexical_Structure.md#static-string-literal)