Merge pull request #1076 from Nemocdz/gh-pages

update Swift5.3 beta
This commit is contained in:
DanziChen
2020-07-06 11:51:26 +08:00
committed by GitHub
8 changed files with 1798 additions and 1708 deletions

View File

@ -1,11 +1,11 @@
# 版本兼容性 # 版本兼容性
本书描述的是在 Xcode 11.4 中的默认 Swift 版本 Swift 5.2。你可以使用 Xcode11.4 来构建 Swift 5.1、Swift 4.2 或 Swift 4 写的项目。 本书描述的是在 Xcode 12 中的默认 Swift 版本 Swift 5.3。你可以使用 Xcode 12 来构建 Swift 5.3、Swift 4.2 或 Swift 4 写的项目。
当您使用 Xcode 11.4 构建 Swift 4 和 Swift 4.2 代码时Swift 5.2 的大多数功能都适用。但以下功能仅支持 Swift 5.2 或更高版本: 当您使用 Xcode 12 构建 Swift 4 和 Swift 4.2 代码时Swift 5.3 的大多数功能都适用。但以下功能仅支持 Swift 5.3 或更高版本:
* 返回值是不透明类型的函数依赖 Swift 5.1 运行时。 * 返回值是不透明类型的函数依赖 Swift 5.1 运行时。
* **try?** 表达式不会为已返回可选类型的代码引入额外的可选类型层级。 * **try?** 表达式不会为已返回可选类型的代码引入额外的可选类型层级。
* 大数字的整型字面量初始化代码的类型将会被正确推导,例如 **UInt64(0xffff_ffff_ffff_ffff)** 将会被推导为整型类型而非溢出。 * 大数字的整型字面量初始化代码的类型将会被正确推导,例如 **UInt64(0xffff_ffff_ffff_ffff)** 将会被推导为整型类型而非溢出。
用 Swift 5.2 写的项目可以依赖用 Swift 4.2 或 Swift 4 写的项目反之亦然。这意味着如果你将一个大的项目分解成多个框架framework你可以逐个地将框架从 Swift 4 代码迁移到 Swift 5.2 用 Swift 5.3 写的项目可以依赖用 Swift 4.2 或 Swift 4 写的项目反之亦然。这意味着如果你将一个大的项目分解成多个框架framework你可以逐个地将框架从 Swift 4 代码迁移到 Swift 5.3

View File

@ -2,7 +2,7 @@
*运算符*是检查、改变、合并值的特殊符号或短语。例如,加号(`+`)将两个数相加(如 `let i = 1 + 2`)。更复杂的运算例子包括逻辑与运算符 `&&`(如 `if enteredDoorCode && passedRetinaScan`)。 *运算符*是检查、改变、合并值的特殊符号或短语。例如,加号(`+`)将两个数相加(如 `let i = 1 + 2`)。更复杂的运算例子包括逻辑与运算符 `&&`(如 `if enteredDoorCode && passedRetinaScan`)。
Swift 支持大部分标准 C 语言的运算符,且为了减少常见编码错误做了部分改进。如:赋值符(`=`)不再有返回值,这样就消除了手误将判等运算符(`==`)写成赋值符导致代码错误的缺陷。算术运算符(`+``-``*``/``%` 等)的结果会被检测并禁止值溢出,以此来避免保存变量时由于变量大于或小于其类型所能承载的范围时导致的异常结果。当然允许你使用 Swift 的溢出运算符来实现溢出。详情参见 [溢出运算符](./27_Advanced_Operators.md#overflow-operators)。 Swift 支持运算符你可能在别的语言比如 C 语言里已经认识了,同时为了减少常见编码错误对它们做了部分改进。如:赋值符(`=`)不再有返回值,这样就消除了手误将判等运算符(`==`)写成赋值符导致代码错误的缺陷。算术运算符(`+``-``*``/``%` 等)的结果会被检测并禁止值溢出,以此来避免保存变量时由于变量大于或小于其类型所能承载的范围时导致的异常结果。当然允许你使用 Swift 的溢出运算符来实现溢出。详情参见 [溢出运算符](./27_Advanced_Operators.md#overflow-operators)。
Swift 还提供了 C 语言没有的区间运算符,例如 `a..<b``a...b`,这方便我们表达一个区间内的数值。 Swift 还提供了 C 语言没有的区间运算符,例如 `a..<b``a...b`,这方便我们表达一个区间内的数值。
@ -157,7 +157,7 @@ a += 2
## 比较运算符Comparison Operators {#comparison-operators} ## 比较运算符Comparison Operators {#comparison-operators}
所有标准 C 语言中的*比较运算符*都可以在 Swift 中使用 Swift 支持以下的比较运算符
- 等于(`a == b` - 等于(`a == b`
- 不等于(`a != b` - 不等于(`a != b`

View File

@ -269,6 +269,20 @@ let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
`multiplier` 的值也作为字符串中后面表达式的一部分。该表达式计算 `Double(multiplier) * 2.5` 的值并将结果(`7.5`)插入到字符串中。在这个例子中,表达式写为 `\(Double(multiplier) * 2.5)` 并包含在字符串字面量中。 `multiplier` 的值也作为字符串中后面表达式的一部分。该表达式计算 `Double(multiplier) * 2.5` 的值并将结果(`7.5`)插入到字符串中。在这个例子中,表达式写为 `\(Double(multiplier) * 2.5)` 并包含在字符串字面量中。
你可以使用扩展字符串分隔符创建字符串,来包含不想作为字符串插值处理的字符。例如:
```swift
print(#"Write an interpolated string in Swift using \(multiplier)."#)
// 打印 "Write an interpolated string in Swift using \(multiplier)."
```
如果要在使用扩展字符串分隔符的字符串中使用字符串插值,需要在反斜杠后面添加与开头和结尾数量相同扩展字符串分隔符。例如:
```swift
print(#"6 times 7 is \#(6 * 7)."#)
// 打印 "6 times 7 is 42."
```
> 注意 > 注意
> >
> 插值字符串中写在括号中的表达式不能包含非转义反斜杠(`\`),并且不能包含回车或换行符。不过,插值字符串可以包含其他字面量。 > 插值字符串中写在括号中的表达式不能包含非转义反斜杠(`\`),并且不能包含回车或换行符。不过,插值字符串可以包含其他字面量。

View File

@ -142,6 +142,8 @@ do {
statements statements
} catch pattern 2 where condition { } catch pattern 2 where condition {
statements statements
} catch pattern 3, pattern 4 where condition {
statements
} catch { } catch {
statements statements
} }
@ -180,7 +182,7 @@ func nourish(with item: String) throws {
do { do {
try vendingMachine.vend(itemNamed: item) try vendingMachine.vend(itemNamed: item)
} catch is VendingMachineError { } catch is VendingMachineError {
print("Invalid selection, out of stock, or not enough money.") print("Couldn't buy that from the vending machine.")
} }
} }
@ -189,11 +191,27 @@ do {
} catch { } catch {
print("Unexpected non-vending-machine-related error: \(error)") print("Unexpected non-vending-machine-related error: \(error)")
} }
// 打印“Invalid selection, out of stock, or not enough money.” // 打印“Couldn't buy that from the vending machine.”
``` ```
如果 `vend(itemNamed:)` 抛出的是一个 `VendingMachineError` 类型的错误,`nourish(with:)` 会打印一条消息,否则 `nourish(with:)` 会将错误抛给它的调用方。这个错误之后会被通用的 `catch` 语句捕获。 如果 `vend(itemNamed:)` 抛出的是一个 `VendingMachineError` 类型的错误,`nourish(with:)` 会打印一条消息,否则 `nourish(with:)` 会将错误抛给它的调用方。这个错误之后会被通用的 `catch` 语句捕获。
另一种捕获多个相关错误的方式是将它们放在 `catch` 后,通过逗号分隔。
例如:
```swift
func eat(item: String) throws {
do {
try vendingMachine.vend(itemNamed: item)
} catch VendingMachineError.invalidSelection, VendingMachineError.insufficientFunds, VendingMachineError.outOfStock {
print("Invalid selection, out of stock, or not enough money.")
}
}
```
`eat(item:)` 函数捕获了列出来的 `VendingMachine` 错误,且它的错误文本和列表的错误相关。如果列出来的三个错误中任意一个抛出,这个 `catch` 代码块就会打印信息。其他错误会传递到外面的作用域,包括以后可能添加的其他 `VendingMachine` 错误。
### 将错误转换成可选值 {#converting-errors-to-optional-values} ### 将错误转换成可选值 {#converting-errors-to-optional-values}
可以使用 `try?` 通过将错误转换成一个可选值来处理错误。如果是在计算 `try?` 表达式时抛出错误,该表达式的结果就为 `nil`。例如,在下面的代码中,`x``y` 有着相同的数值和等价的含义: 可以使用 `try?` 通过将错误转换成一个可选值来处理错误。如果是在计算 `try?` 表达式时抛出错误,该表达式的结果就为 `nil`。例如,在下面的代码中,`x``y` 有着相同的数值和等价的含义:

View File

@ -152,7 +152,7 @@ Swift 的*“词法结构lexical structure”* 描述了能构成该语言
* 用在语句中的关键字:`break``case``continue``default``defer``do``else``fallthrough``for``guard``if``in``repeat``return``switch``where` 以及 `while` * 用在语句中的关键字:`break``case``continue``default``defer``do``else``fallthrough``for``guard``if``in``repeat``return``switch``where` 以及 `while`
* 用在表达式和类型中的关键字:`as``Any``catch``false``is``nil``super``self``Self``throw``throws``true` 以及 `try ` * 用在表达式和类型中的关键字:`as``Any``catch``false``is``nil``super``self``Self``throw``throws``true` 以及 `try `
* 用在模式中的关键字:`_` * 用在模式中的关键字:`_`
* 以井字号(`#`)开头的关键字:`#available``#colorLiteral``#column``#else``#elseif``#endif``#error``#file``#fileLiteral``#function``#if``#imageLiteral``#line``#selector``#sourceLocation`以及 `#warning` * 以井字号(`#`)开头的关键字:`#available``#colorLiteral``#column``#else``#elseif``#endif``#error``#file``#filePath``#fileLiteral``#function``#if``#imageLiteral``#line``#selector``#sourceLocation`以及 `#warning`
* 特定上下文中被保留的关键字:`associativity``convenience``dynamic``didSet``final``get``infix``indirect``lazy``left``mutating``none``nonmutating``optional``override``postfix``precedence``prefix``Protocol``required``right``set``Type``unowned``weak` 以及 `willSet`。这些关键字在特定上下文之外可以被用做标识符。 * 特定上下文中被保留的关键字:`associativity``convenience``dynamic``didSet``final``get``infix``indirect``lazy``left``mutating``none``nonmutating``optional``override``postfix``precedence``prefix``Protocol``required``right``set``Type``unowned``weak` 以及 `willSet`。这些关键字在特定上下文之外可以被用做标识符。
以下符号被保留为标点符号,不能用于自定义运算符:`(``)``{``}``[``]``.``,``:``;``=``@``#``&`(作为前缀运算符)、`->`、`` ` ``、`?`、以及 `!`(作为后缀运算符)。 以下符号被保留为标点符号,不能用于自定义运算符:`(``)``{``}``[``]``.``,``:``;``=``@``#``&`(作为前缀运算符)、`->`、`` ` ``、`?`、以及 `!`(作为后缀运算符)。

View File

@ -9,7 +9,6 @@ Swift 中存在四种表达式:前缀表达式,二元表达式,基本表
#### expression {#expression} #### expression {#expression}
> *表达式* → [try 运算符](#try-operator)<sub>可选</sub> [前缀表达式](#prefix-expression) [二元表达式列表](#binary-expressions)<sub>可选</sub> > *表达式* → [try 运算符](#try-operator)<sub>可选</sub> [前缀表达式](#prefix-expression) [二元表达式列表](#binary-expressions)<sub>可选</sub>
>
#### expression-list {#expression-list} #### expression-list {#expression-list}
@ -232,11 +231,18 @@ f(x as Any)
字面量 | 类型 | 值 字面量 | 类型 | 值
:------------- | :---------- | :---------- :------------- | :---------- | :----------
`#file` | `String` | 所在的文件名 `#file` | `String` | 所在的文件名及模块
`#filePath` | `String` | 所在的文件路径
`#line` | `Int` | 所在的行数 `#line` | `Int` | 所在的行数
`#column` | `Int` | 所在的列数 `#column` | `Int` | 所在的列数
`#function` | `String` | 所在的声明的名字 `#function` | `String` | 所在的声明的名字
`#dsohandle` | `UnsafeRawPointer` | 所使用的 DSO动态共享对象句柄
`#file` 表达式的值的格式是 *module*/*file**file* 是表达式所在的文件名,*module* 是文件所所在的模块名。`#filePath` 表达式的字符串值是表达式所在的文件在整个文件系统里的路径。所有这些值可以被 `#sourceLocation` 改变,详见 [行控制语句](./05_Statements.md#line-control-statements)。
> 注意
>
> 要解析 `#file` 表达式,第一个斜杠(/)之前的文本作为模块名,最后一个斜杠之后的文本作为文件名。将来,该字符串可能包含多个斜杠,例如 `MyModule/some/disambiguation/MyFile.swift`。
对于 `#function`,在函数中会返回当前函数的名字,在方法中会返回当前方法的名字,在属性的存取器中会返回属性的名字,在特殊的成员如 `init``subscript` 中会返回这个关键字的名字,在某个文件中会返回当前模块的名字。 对于 `#function`,在函数中会返回当前函数的名字,在方法中会返回当前方法的名字,在属性的存取器中会返回属性的名字,在特殊的成员如 `init``subscript` 中会返回这个关键字的名字,在某个文件中会返回当前模块的名字。
@ -288,7 +294,7 @@ Xcode 使用 playground 字面量对程序编辑器中的颜色、文件或者
> >
> *字面量表达式* → [数组字面量](#array-literal) | [字典字面量](#dictionary-literal) | [练习场字面量](#playground-literal) > *字面量表达式* → [数组字面量](#array-literal) | [字典字面量](#dictionary-literal) | [练习场字面量](#playground-literal)
> >
> *字面量表达式* → **#file** | **#line** | **#column** | **#function** > *字面量表达式* → **#file** **#filePath** | **#line** | **#column** | **#function**
> >
@ -757,7 +763,7 @@ print(count as Any)
// 打印 "Optional(5)" // 打印 "Optional(5)"
``` ```
可以混合使用各种 key-path 组件来访问一些深度嵌套类型的值。下面的代码通过组合不同的组件,使用 key-path 表达式访问了一个字典数组中不同的值和属性。 可以混合使用各种 key path 组件来访问一些深度嵌套类型的值。下面的代码通过组合不同的组件,使用 key-path 表达式访问了一个字典数组中不同的值和属性。
```swift ```swift
let interestingNumbers = ["prime": [2, 3, 5, 7, 11, 13, 17], let interestingNumbers = ["prime": [2, 3, 5, 7, 11, 13, 17],
@ -773,6 +779,39 @@ print(interestingNumbers[keyPath: \[String: [Int]].["hexagonal"]!.count.bitWidth
// 打印 "64" // 打印 "64"
``` ```
你可以在平时提供函数或者闭包的上下文里使用 key path 表达式。特别地,你可以用根类型是 `SomeType` 和路径产生 `Value` 类型值的 key path 表达式来替换类型是 `(SomeType) -> Value` 的函数或者闭包。
```swift
struct Task {
var description: String
var completed: Bool
}
var toDoList = [
Task(description: "Practice ping-pong.", completed: false),
Task(description: "Buy a pirate costume.", completed: true),
Task(description: "Visit Boston in the Fall.", completed: false),
]
// 下面两种写法是等价的。
let descriptions = toDoList.filter(\.completed).map(\.description)
let descriptions2 = toDoList.filter { $0.completed }.map { $0.description }
```
任何 key path 表达式的副作用发生的关键在于表达式在哪里被执行。例如,如果你在 key path 表达式中的一个下标里使用函数调用,该函数只会在表达式计算的时候调用一次,而不是每次这个 key path 被使用的时候。
```swift
func makeIndex() -> Int {
print("Made an index")
return 0
}
// 下面这行调用 makeIndex()。
let taskKeyPath = \[Task][makeIndex()]
// 打印 "Made an index"
// 使用 taskKeyPath 不会再次调用 makeIndex()。
let someTask = toDoList[keyPath: taskKeyPath]
```
关于更多如何使用 key path 与 Objective-C APIs 交互的信息,请参阅 [在 Swift 中使用 Objective-C 运行时特性](https://developer.apple.com/documentation/swift/using_objective_c_runtime_features_in_swift)。关于更多 key-value 编程和 key-value 观察的信息,请参阅 [Key-Value 编程](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueCoding/index.html#//apple-ref/doc/uid/10000107i) 和 [Key-Value 观察编程](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html#//apple-ref/doc/uid/10000177i)。 关于更多如何使用 key path 与 Objective-C APIs 交互的信息,请参阅 [在 Swift 中使用 Objective-C 运行时特性](https://developer.apple.com/documentation/swift/using_objective_c_runtime_features_in_swift)。关于更多 key-value 编程和 key-value 观察的信息,请参阅 [Key-Value 编程](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueCoding/index.html#//apple-ref/doc/uid/10000107i) 和 [Key-Value 观察编程](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html#//apple-ref/doc/uid/10000177i)。
> key-path 表达式语法 > key-path 表达式语法
@ -959,14 +998,17 @@ print(keyPath == c.getSomeKeyPath())
如果函数声明中指定了参数的名字,那么在调用的时候也必须得写出来。这种函数调用表达式具有以下形式: 如果函数声明中指定了参数的名字,那么在调用的时候也必须得写出来。这种函数调用表达式具有以下形式:
> `函数名`(`参数名 1`: `参数 1`, `参数名 2`: `参数 2`) > `函数名`(`参数名 1`: `参数 1`, `参数名 2`: `参数 2`)
>
如果函数的最后一个参数是函数类型,可以在函数调用表达式的尾部(右圆括号之后)加上一个闭包,该闭包会作为函数的最后一个参数。如下两种写法是等价的: 如果函数的最后一个参数是函数类型,可以在函数调用表达式的尾部(右圆括号之后)加上一个闭包,该闭包会作为函数的最后一个参数。如下两种写法是等价的:
```swift ```swift
// someFunction 接受整和闭包参 // someFunction 接受整和闭包的实
someFunction(x, f: {$0 == 13}) someFunction(x, f: {$0 == 13})
someFunction(x) {$0 == 13} someFunction(x) {$0 == 13}
// anotherFunction 接受一个整型和两个闭包的实参
anotherFunction(x: x, f: { $0 == 13 }, g: { print(99) })
anotherFunction(x: x) { $0 == 13 } g: { print(99) }
``` ```
如果闭包是该函数的唯一参数,那么圆括号可以省略。 如果闭包是该函数的唯一参数,那么圆括号可以省略。
@ -988,30 +1030,32 @@ myData.someMethod {$0 == 13}
> >
> *函数调用表达式* → [后缀表达式](#postfix-expression) [函数调用参数子句](#function-call-argument-clause)<sub>可选</sub> [尾随闭包](#trailing-closure) > *函数调用表达式* → [后缀表达式](#postfix-expression) [函数调用参数子句](#function-call-argument-clause)<sub>可选</sub> [尾随闭包](#trailing-closure)
> >
>#### function-call-argument-clause {#function-call-argument-clause}
> >
>
#### function-call-argument-clause {#function-call-argument-clause}
>
> *函数调用参数子句* → **(** **)** | **(** [函数调用参数表](#function-call-argument-list) **)** > *函数调用参数子句* → **(** **)** | **(** [函数调用参数表](#function-call-argument-list) **)**
> >
> > #### function-call-argument-list {#function-call-argument-list}
#### function-call-argument-list {#function-call-argument-list}
> >
> *函数调用参数表* → [函数调用参数](#function-call-argument) | [函数调用参数](#function-call-argument) **,** [*函数调用参数表*](#function-call-argument-list) > *函数调用参数表* → [函数调用参数](#function-call-argument) | [函数调用参数](#function-call-argument) **,** [*函数调用参数表*](#function-call-argument-list)
> >
> >
#### function-call-argument {#function-call-argument} > #### function-call-argument {#function-call-argument}
> >
> *函数调用参数* → [表达式](#expression) | [标识符](02-Lexical-Structure.md#identifier) **:** [表达式](#expression) > *函数调用参数* → [表达式](#expression) | [标识符](02-Lexical-Structure.md#identifier) **:** [表达式](#expression)
> >
> *函数调用参数* → [运算符](./02_Lexical_Structure.md#operator) | [标识符](./02-Lexical-Structure.md#identifier) **:** [运算符](./02-Lexical-Structure.md#operator) > *函数调用参数* → [运算符](./02_Lexical_Structure.md#operator) | [标识符](./02-Lexical-Structure.md#identifier) **:** [运算符](./02-Lexical-Structure.md#operator)
> >
> > #### trailing-closure {#trailing-closure}
>
#### trailing-closure {#trailing-closure}
> >
> *尾随闭包* → [闭包表达式](#closure-expression) > *尾随闭包* → [闭包表达式](#closure-expression)
>
> #### labeled-trailing-closures {#labeled-trailing-closures}
> >
> *标签尾随闭包集* → [标签尾随闭包](#labeled-trailing-closure) [标签尾随闭包集](#labeled-trailing-closures)<sub>可选</sub>
>
> #### labeled-trailing-closure {#labeled-trailing-closure}
> *标签尾随闭包* → [标识符](./02-Lexical-Structure.md#identifier) **:** [闭包表达式](#closure-expression)
### 构造器表达式 {#initializer-expression} ### 构造器表达式 {#initializer-expression}
*构造器表达式*用于访问某个类型的构造器,形式如下: *构造器表达式*用于访问某个类型的构造器,形式如下:

View File

@ -577,10 +577,18 @@ do {
statements statements
} catch pattern 2 where condition { } catch pattern 2 where condition {
statements statements
} catch pattern 3, pattern 4 where condition {
statements
} catch {
statements
} }
``` ```
`switch` 语句,编译器会判断 `catch` 子句是否有遗漏。如果 `catch` 子句没有遗漏,则认为错误已被处理。否则,错误会自动传递到外作用域,被某个 `catch` 子句处理掉或者被用 `throws` 关键字声明的抛出函数继续向外抛出 `do` 代码块中的任何语句抛出了错误,程序会跳转到第一个能模式匹配该错误的 `catch` 子句。如果没有任何子句匹配,错误会传递到外层作作用域。如果错误在最顶层依旧没有被处理,程序执行会因为运行时错误而停止
如同 `switch` 语句,编译器会判断 `catch` 子句是否有遗漏。如果 `catch` 子句没有遗漏,则认为错误已被处理。否则,错误会自动传递到外层作用域,被某个 `catch` 子句处理掉或者被用 `throws` 关键字声明的抛出函数继续向外抛出。
拥有多个模式匹配的 `catch` 子句只需其中一个匹配到错误即可。如果 `catch` 子句拥有多个模式匹配,所有的模式必须包含相同的绑定常量或变量,并且每个 `catch` 子句里所有绑定的变量或常量的类型必须相同。
为了确保错误已经被处理,可以让 `catch` 子句使用匹配所有错误的模式,如通配符模式(`_`)。如果一个 `catch` 子句不指定一种具体模式,`catch` 子句会匹配任何错误,并绑定到名为 `error` 的局部常量。有关在 `catch` 子句中使用模式的更多信息,请参阅 [模式](./08_Patterns.md)。 为了确保错误已经被处理,可以让 `catch` 子句使用匹配所有错误的模式,如通配符模式(`_`)。如果一个 `catch` 子句不指定一种具体模式,`catch` 子句会匹配任何错误,并绑定到名为 `error` 的局部常量。有关在 `catch` 子句中使用模式的更多信息,请参阅 [模式](./08_Patterns.md)。
@ -600,7 +608,12 @@ do {
#### catch-clause {#catch-clause} #### catch-clause {#catch-clause}
> *catch 子句* → **catch** [模式](./08_Patterns.md#pattern)<sub>可选</sub> [where 子句](#where-clause)<sub>可选</sub> [代码块](05-Declarations.md#code-block) > *catch 子句* → **catch** [模式](./08_Patterns.md#pattern)<sub>可选</sub> [where 子句](#where-clause)<sub>可选</sub> [代码块](05-Declarations.md#code-block)
>
#### catch-pattern-list{#catch-pattern-list}
> *catch 模式列表* → [catch 模式](#catch-pattern) | [catch 模式](#catch-pattern) [catch 模式列表](#catch-pattern-list)
#### catch-pattern{#catch-pattern}
> *catch 模式* → [模式](./08_Patterns.md#pattern) [where 子句](./05-Statements.md#where-clause)<sub>可选</sub>
## 编译器控制语句 {#compiler-control-statements} ## 编译器控制语句 {#compiler-control-statements}
编译器控制语句允许程序改变编译器的行为。Swift 有三种编译器控制语句:条件编译语句、线路控制语句和编译时诊断语句。 编译器控制语句允许程序改变编译器的行为。Swift 有三种编译器控制语句:条件编译语句、线路控制语句和编译时诊断语句。
@ -789,13 +802,11 @@ statements to compile if both compilation conditions are false
行控制语句形式如下: 行控制语句形式如下:
> \#sourceLocation(file: `filename` , line:`line number`) > #sourceLocation(file: file path, line: line number)
> >
> #sourceLocation()
> \#sourceLocation() 第一种的行控制语句会改变该语句之后的代码中的字面量表达式 `#line``#file``#filePath` 所表示的值,从行控制语句里行号的代码开始。`行号` 是一个大于 0 的整形字面量,会改变 `#line` 表达式的值。`文件名` 是一个字符串字面量,会改变 `#file``#filePath` 表达式的值。指定的字符串会变成 `#filePath` 的值,且字符串最后的路径部分会变成 `#file` 的值。
>
第一种的行控制语句会改变该语句之后的代码中的字面量表达式 `#line``#file` 所表示的值。`行号` 是一个大于 0 的整形字面量,会改变 `#line` 表达式的值。`文件名` 是一个字符串字面量,会改变 `#file` 表达式的值。
第二种的行控制语句,`#sourceLocation()`,会将源代码的定位信息重置回默认的行号和文件名。 第二种的行控制语句,`#sourceLocation()`,会将源代码的定位信息重置回默认的行号和文件名。

File diff suppressed because it is too large Load Diff