diff --git a/source/chapter3/10_Statements.md b/source/chapter3/10_Statements.md index 5aff0508..abd6a674 100755 --- a/source/chapter3/10_Statements.md +++ b/source/chapter3/10_Statements.md @@ -16,9 +16,9 @@ - [带标签的语句](#labeled_statement) - [控制传递语句](#control_transfer_statements) -在 Swift 中,有两种类型的语句:简单语句和控制流语句。简单语句是最常见的,用于构造表达式或者声明。控制流语句则用于控制程序执行的流程,Swift 中有三种类型的控制流语句:循环语句、分支语句和控制传递语句。 +在 Swift 中,有三种类型的语句:简单语句、编译控制语句和控制流语句。简单语句是最常见的,用于构造表达式或者声明。编译控制语句允许程序改变编译器的行为以及包含构建配置和源代码控制语句。 -循环语句用于重复执行代码块;分支语句用于执行满足特定条件的代码块;控制传递语句则用于修改代码的执行顺序。在稍后的叙述中,将会详细地介绍每一种类型的控制流语句。 +控制流语句则用于控制程序执行的流程,Swift 中有几种类型的控制流语句:循环语句、分支语句和控制传递语句。循环语句用于重复执行代码块;分支语句用于执行满足特定条件的代码块;控制传递语句则用于修改代码的执行顺序。另外,Swift 提供了 `do` 语句来引入范围以及捕获和处理错误,还提供了 `defer` 语句在退出当前范围之前执行清理操作。 是否将分号(`;`)添加到语句的结尾处是可选的。但若要在同一行内写多条独立语句,请务必使用分号。 @@ -467,11 +467,8 @@ swift 中的 do 语句与C 中限定代码块界限的大括号 ({})很相 `statements` > } - 如同`switch`语句,编译器会判断`catch`子句是否被遗漏。如果catch没有被遗漏,则认为错误被处理。否则,错误会自动传播出包含作用域,被一个封闭的`catch`语句或抛出函数处理掉,包含函数必须以`throws`关键字声明。 - - 为了确保错误已经被处理,使用一个匹配所有错误的`catch`子句,如通配符模式(_)。如果一个`catch`子句不指定一种模式,`catch`子句会匹配和约束任何局部变量命名的`error`。有关在`catch`子句中使用模式的更多信息,详见[模式](TODO)。 关于在一些`catch`子句中如何使用` do`语句的例子,详情参见[错误处理](TODO)一章的[抛出错误](TODO)。 @@ -480,6 +477,101 @@ swift 中的 do 语句与C 中限定代码块界限的大括号 ({})很相 > catch → *[catch子句](TODO) [catch子句](TODO)* > catch → **catch** *[*模式*](../chapter3/07_Patterns.html#pattern)** *可选的* [*where*]() *可选的* [*代码块*](../chapter3/05_Declarations.html#code_block) + +### 编译控制语句 + +编译控制语句允许程序改变编译器的行为。Swift 有两种编译控制语句:构建配置语句和源代码控制语句。 + +> 编译控制语句语法 +> *编译控制语句* → [*构建配置语句*](../chapter3/04_Expressions.html#build_config_statements) +> *编译控制语句* → [*源代码控制语句*](../chapter3/04_Expressions.html#line_control_statements) + + +#### 构建配置语句 + +构建配置语句可以根据一个或多个配置项来有条件的编译代码。 + +每一个构建配置语句都以 `#if` 开始, `#endif` 结束。如下是一个简单的构建配置语句: + +``` +#if build configuration +statements +#endif +``` + +和 `if` 语句的条件不同,构建配置的条件是在编译时进行判断的。它的结果是:只有构建配置在编译时判断为 `true` 的情况下语句才会被编译和执行。 + +*构建配置* 可以是 `true` 和 `false` 的常量,也可以是使用 `-D` 命令行标志的标识符,或者是下列表格中的任意一个平台测试方法。 + + | 方法 | 可用参数 | + | --- | - | + | os() | OSX, iOS, watchOS, tvOS | + | arch() | i386, x86_64, arm, arm64 | + + +> 注意 +> `arch(arm)` 构建配置在 ARM 64位设备上不会返回 `true`。如果代码的构建目标是 32 位的 iOS 模拟器,`arch(i386)` 构建配置返回 `true`。 + +你可以使用逻辑操作符 `&&`、`||` 和 `!` 来连接构建配置,还可以使用圆括号来进行分组。 + +就像 `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 +#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­ + + +#### 源代码控制语句 + +源代码控制语句用来给被编译源代码指定一个与原始行号和文件名不同的行号和文件名。使用源代码控制语句可以改变 Swift 使用源代码的位置,以便进行分析和测试。 + +源代码的控制语句的例子如下: + +``` +#line line number filename +``` + +源代码控制语句改变了常量表达式 `__LINE__` 和 `__FILE__` 的值,以一行源代码开头,然后跟着源代码控制语句。`line number` 改变了 `__LINE__` 的值,它是一个大于 0 的常量。`filename` 改变了 `__FILE__` 的值,它是一个字符串常量。 + +你可以通过写一句不指定 `line number` 和 `filename` 的源代码控制语句来吧源代码的位置回退到初始的行号和文件。 + +源代码控制语句必须出现在源代码的那一行,而且不能是源代码文件的最后一行。 + +> 源代码控制语句 + +> 源代码控制语句 → #line­ +> 源代码控制语句 → #line­ line-number­ file-name­ +> line-number → 大于 0 的十进制数 +> file-name → 字符串常量 + +