更新内容到 Swift 5.5 (#1156)
* Advanced_Operators Swift 5.3 beata * feat: update Opaque Types Swift 5.5 * feat: update Properties Swift 5.5 * feat: update AdvancedOperators Swift 5.5 * fix: 根据校对意见修改 * feat: update Statements to Swift 5.5 * feat: [wip] experssion to Swift 5.5 * feat: update Expression to Swift 5.5
This commit is contained in:
@ -15,7 +15,6 @@ Swift 的*“词法结构(lexical structure)”* 描述了能构成该语言
|
||||
> 空白语法
|
||||
>
|
||||
> *空白* → [空白项](#whitespace-item) [空白](#whitespace)<sub>可选</sub>
|
||||
>
|
||||
#### whitespace-item {#whitespace-item}
|
||||
>
|
||||
> *空白项* → [断行符](#line-break)
|
||||
@ -78,12 +77,16 @@ Swift 的*“词法结构(lexical structure)”* 描述了能构成该语言
|
||||
|
||||
> 标识符语法
|
||||
>
|
||||
> #### identifier {#identifier}
|
||||
>
|
||||
> *标识符* → [头部标识符](#identifier-head) [标识符字符组](#identifier-characters)<sub>可选</sub>
|
||||
>
|
||||
> *标识符* → \`[头部标识符](#identifier-head) [标识符字符组](#identifier-characters)<sub>可选</sub>\`
|
||||
>
|
||||
> *标识符* → [隐式参数名](#implicit-parameter-name)
|
||||
>
|
||||
> #### identifier-list {#identifier-list}
|
||||
>
|
||||
> *标识符列表* → [标识符](#identifier) | [标识符](#identifier) **,** [标识符列表](#identifier)
|
||||
>
|
||||
>
|
||||
@ -120,7 +123,6 @@ Swift 的*“词法结构(lexical structure)”* 描述了能构成该语言
|
||||
> *头部标识符* → U+90000–U+9FFFD,U+A0000–U+AFFFD,U+B0000–U+BFFFD,或者 U+C0000–U+CFFFD
|
||||
>
|
||||
> *头部标识符* → U+D0000–U+DFFFD 或者 U+E0000–U+EFFFD
|
||||
>
|
||||
#### identifier-character {#identifier-character}
|
||||
>
|
||||
> *标识符字符* → 数值 0 - 9
|
||||
@ -138,11 +140,9 @@ Swift 的*“词法结构(lexical structure)”* 描述了能构成该语言
|
||||
#### implicit-parameter-name {#implicit-parameter-name}
|
||||
>
|
||||
> *隐式参数名* → **$** [十进制数字列表](#decimal-digit)
|
||||
>
|
||||
#### property-wrapper-projection {#property-wrapper-projection}
|
||||
>
|
||||
> *属性包装器呈现值* → **$** [标识符字符组](#identifier-characters)
|
||||
>
|
||||
|
||||
## 关键字和标点符号 {#keywords-and-punctuation}
|
||||
|
||||
|
||||
@ -5,15 +5,13 @@ Swift 中存在四种表达式:前缀表达式,二元表达式,基本表
|
||||
通过前缀表达式和二元表达式可以对简单表达式使用各种运算符。基本表达式从概念上讲是最简单的一种表达式,它是一种访问值的方式。后缀表达式则允许你建立复杂的表达式,例如函数调用和成员访问。每种表达式都在下面有详细论述。
|
||||
|
||||
> 表达式语法
|
||||
>
|
||||
|
||||
#### expression {#expression}
|
||||
> *表达式* → [try 运算符](#try-operator)<sub>可选</sub> [前缀表达式](#prefix-expression) [二元表达式列表](#binary-expressions)<sub>可选</sub>
|
||||
> *表达式* → [try 运算符](#try-operator)<sub>可选</sub> [await 运算符](#await-operator)<sub>可选</sub> [前缀表达式](#prefix-expression) [二元表达式列表](#binary-expressions)<sub>可选</sub>
|
||||
|
||||
#### expression-list {#expression-list}
|
||||
|
||||
> *表达式列表* → [表达式](#expression) | [表达式](#expression) **,** [表达式列表](#expression-list)
|
||||
>
|
||||
|
||||
## 前缀表达式 {#prefix-expressions}
|
||||
前缀表达式由可选的前缀运算符和表达式组成。前缀运算符只接收一个参数,表达式则紧随其后。
|
||||
@ -25,61 +23,110 @@ Swift 中存在四种表达式:前缀表达式,二元表达式,基本表
|
||||
除了标准库运算符,你也可以对某个变量使用 `&` 运算符,从而将其传递给函数的输入输出参数。更多信息,请参阅 [输入输出参数](../02_language_guide/06_Functions.md#in-out-parameters)。
|
||||
|
||||
> 前缀表达式语法
|
||||
>
|
||||
|
||||
#### prefix-expression {#prefix-expression}
|
||||
> *前缀表达式* → [前缀运算符](./02_Lexical_Structure.md#prefix-operator)<sub>可选</sub> [后缀表达式](#postfix-expression)
|
||||
>
|
||||
> *前缀表达式* → [输入输出表达式](#in-out-expression)
|
||||
>
|
||||
|
||||
### 输入输出表达式
|
||||
|
||||
*输入输出表达式* 将函数调用表达式传入的变量标记为输入输出实参。
|
||||
|
||||
> &`表达式`
|
||||
|
||||
更多关于输入输出形参的信息和例子,请参阅 [输入输出形参](../02_language_guide/06_Functions.md#in-out-parameters)。
|
||||
|
||||
输入输出表达式也可以用于将非指针实参传入到需要指针的上下文中,如 [指针类型的隐式转换](#implicit-conversion-to-a-pointer) 中所述。
|
||||
|
||||
#### in-out-expression {#in-out-expression}
|
||||
> *输入输出表达式* → **&** [标识符](./02_Lexical_Structure.md#identifier)
|
||||
>
|
||||
|
||||
### Try 运算符 {#try-operator}
|
||||
try 表达式由 `try` 运算符加上紧随其后的可抛出错误的表达式组成,形式如下:
|
||||
|
||||
> try `可抛出错误的表达式`
|
||||
>
|
||||
*try 表达式*由 `try` 运算符加上紧随其后的可抛出错误的表达式组成,形式如下:
|
||||
|
||||
可选的 try 表达式由 `try?` 运算符加上紧随其后的可抛出错误的表达式组成,形式如下:
|
||||
> try `表达式`
|
||||
|
||||
> try? `可抛出错误的表达式`
|
||||
>
|
||||
`try` 表达式的返回值是该*表达式*的值。
|
||||
|
||||
如果可抛出错误的表达式没有抛出错误,整个表达式返回的可选值将包含可抛出错误的表达式的返回值,否则,该可选值为 `nil`。
|
||||
*可选 try 表达式*由 `try?` 运算符加上紧随其后的可抛出错误的表达式组成,形式如下:
|
||||
|
||||
强制的 try 表达式由 `try!` 运算符加上紧随其后的可抛出错误的表达式组成,形式如下:
|
||||
> try? `表达式`
|
||||
|
||||
> try! `可抛出错误的表达式`
|
||||
>
|
||||
如果*表达式*没有抛出错误,可选 try 表达式的返回值是可选的该*表达式*的值,否则,返回值为 `nil`。
|
||||
|
||||
如果可抛出错误的表达式抛出了错误,将会引发运行时错误。
|
||||
*强制 try 表达式*由 `try!` 运算符加上紧随其后的可抛出错误的表达式组成,形式如下:
|
||||
|
||||
> try! `表达式`
|
||||
|
||||
强制 try 表达式的返回值是该*表达式*的值。如果该*表达式*抛出了错误,将会引发运行时错误。
|
||||
|
||||
在二元运算符左侧的表达式被标记上 `try`、`try?` 或者 `try!` 时,这个运算符对整个二元表达式都产生作用。也就是说,你可以使用括号来明确运算符的作用范围。
|
||||
|
||||
```swift
|
||||
sum = try someThrowingFunction() + anotherThrowingFunction() // try 对两个函数调用都产生作用
|
||||
sum = try (someThrowingFunction() + anotherThrowingFunction()) // try 对两个函数调用都产生作用
|
||||
sum = (try someThrowingFunction()) + anotherThrowingFunction() // 错误:try 只对第一个函数调用产生作用
|
||||
// try 对两个函数调用都产生作用
|
||||
sum = try someThrowingFunction() + anotherThrowingFunction()
|
||||
|
||||
// try 对两个函数调用都产生作用
|
||||
sum = try (someThrowingFunction() + anotherThrowingFunction())
|
||||
|
||||
// 错误:try 只对第一个函数调用产生作用
|
||||
sum = (try someThrowingFunction()) + anotherThrowingFunction()
|
||||
```
|
||||
|
||||
`try` 表达式不能出现在二元运算符的的右侧,除非二元运算符是赋值运算符或者 `try` 表达式是被圆括号括起来的。
|
||||
|
||||
关于 `try`、`try?` 和 `try!` 的更多信息,以及该如何使用的例子,请参阅 [错误处理](../02_language_guide/17_Error_Handling.md)。
|
||||
如果表达式中同时包含 `try` 和 `await` 运算符,`try` 运算符必须在前面。
|
||||
|
||||
更多关于 `try`、`try?` 和 `try!` 的信息,以及该如何使用的例子,请参阅 [错误处理](../02_language_guide/17_Error_Handling.md)。
|
||||
> Try 表达式语法
|
||||
>
|
||||
|
||||
#### try-operator {#try-operator}
|
||||
> *try 运算符* → **try** | **try?** | **try!**
|
||||
>
|
||||
> *try 运算符* → **try** | **try?** | **try!**
|
||||
|
||||
### Await 运算符
|
||||
|
||||
*await 表达式*由 `await` 运算符加上紧随其后的异步操作结果的表达式。形式如下:
|
||||
|
||||
> await `表达式`
|
||||
|
||||
`await` 表达式返回值就是该*表达式*的值。
|
||||
|
||||
被 `await` 标记的表达式被称为*潜在的暂停点*。
|
||||
|
||||
异步函数的执行可以在每个标记 `await` 的表达式的位置暂停。除此之外,并发代码的执行永远不会在其他位置暂停。这意味着在潜在暂停点之间的代码可以暂时打破不变量的状态进行安全更新,只要更新在下一个潜在暂停点之前完成。
|
||||
|
||||
`await` 表达式只能在异步的上下文中出现,比如传入 `async(priority:operation:)` 函数的尾随闭包中。它不能在 `defer` 语句的闭包中,或者在同步函数的自动闭包中出现。
|
||||
|
||||
在二元运算符左侧的表达式被标记上 `await` 运算符时,这个运算符对整个二元表达式都产生作用。也就是说,你可以使用括号来明确运算符的作用范围。
|
||||
|
||||
```swift
|
||||
// await 对两个函数调用都产生作用
|
||||
sum = await someAsyncFunction() + anotherAsyncFunction()
|
||||
|
||||
// await 对两个函数调用都产生作用
|
||||
sum = await (someAsyncFunction() + anotherAsyncFunction())
|
||||
|
||||
// 错误:await 只对第一个函数调用产生作用
|
||||
sum = (await someAsyncFunction()) + anotherAsyncFunction()
|
||||
```
|
||||
|
||||
`await` 表达式不能出现在二元运算符的的右侧,除非二元运算符是赋值运算符或者 `await` 表达式是被圆括号括起来的。
|
||||
|
||||
如果表达式中同时包含 `try` 和 `await` 运算符,`try` 运算符必须在前面。
|
||||
|
||||
> Await 表达式语法
|
||||
|
||||
#### await-operator {#await-operator}
|
||||
> *await 运算符* → **await**
|
||||
|
||||
|
||||
## 二元表达式 {#binary-expressions}
|
||||
|
||||
*二元表达式*由中缀运算符和左右参数表达式组成。形式如下:
|
||||
|
||||
> `左侧参数` `二元运算符` `右侧参数`
|
||||
>
|
||||
|
||||
关于这些运算符的更多信息,请参阅 [基本运算符](../02_language_guide/02_Basic_Operators.md) 和 [高级运算符](../02_language_guide/27_Advanced_Operators.md)。
|
||||
|
||||
@ -88,7 +135,6 @@ sum = (try someThrowingFunction()) + anotherThrowingFunction() // 错误:try
|
||||
> 注意
|
||||
>
|
||||
> 在解析时,一个二元表达式将作为一个扁平列表表示,然后根据运算符的优先级,再进一步进行组合。例如,`2 + 3 * 5` 首先被看作具有五个元素的列表,即 `2`、`+`、`3`、`*`、`5`,随后根据运算符优先级组合为 `(2 + (3 * 5))`。
|
||||
>
|
||||
|
||||
|
||||
#### binary-expression {#binary-expression}
|
||||
@ -101,17 +147,14 @@ sum = (try someThrowingFunction()) + anotherThrowingFunction() // 错误:try
|
||||
> *二元表达式* → [条件运算符](#conditional-operator) [try 运算符](#try-operator)<sub>可选</sub> [前缀表达式](#prefix-expression)
|
||||
>
|
||||
> *二元表达式* → [类型转换运算符](#type-casting-operator)
|
||||
>
|
||||
|
||||
#### binary-expressions {#binary-expressions}
|
||||
> *二元表达式列表* → [二元表达式](#binary-expression) [二元表达式列表](#binary-expressions)<sub>可选</sub>
|
||||
>
|
||||
|
||||
### 赋值表达式 {#assignment-operator}
|
||||
赋值表达式会为某个给定的表达式赋值,形式如下;
|
||||
|
||||
> `表达式` = `值`
|
||||
>
|
||||
|
||||
右边的值会被赋值给左边的表达式。如果左边表达式是一个元组,那么右边必须是一个具有同样元素个数的元组。(嵌套元组也是允许的。)右边的值中的每一部分都会被赋值给左边的表达式中的相应部分。例如:
|
||||
|
||||
@ -123,28 +166,23 @@ sum = (try someThrowingFunction()) + anotherThrowingFunction() // 错误:try
|
||||
赋值运算符不返回任何值。
|
||||
|
||||
> 赋值运算符语法
|
||||
>
|
||||
|
||||
#### assignment-operator {#assignment-operator}
|
||||
> *赋值运算符* → **=**
|
||||
>
|
||||
|
||||
### 三元条件运算符 {#ternary-conditional-operator}
|
||||
*三元条件运算符*会根据条件来对两个给定表达式中的一个进行求值,形式如下:
|
||||
|
||||
> `条件` ? `表达式(条件为真则使用)` : `表达式(条件为假则使用)`
|
||||
>
|
||||
|
||||
如果条件为真,那么对第一个表达式进行求值并返回结果。否则,对第二个表达式进行求值并返回结果。未使用的表达式不会进行求值。
|
||||
|
||||
关于使用三元条件运算符的例子,请参阅 [三元条件运算符](../02_language_guide/02_Basic_Operators.md#ternary-conditional-operator)。
|
||||
|
||||
> 三元条件运算符语法
|
||||
>
|
||||
|
||||
#### conditional-operator {#conditional-operator}
|
||||
> *三元条件运算符* → **?** [表达式](#expression) **:**
|
||||
>
|
||||
|
||||
### 类型转换运算符 {#type-casting-operators}
|
||||
有 4 种类型转换运算符:`is`、`as`、`as? ` 和 `as!`。它们有如下的形式:
|
||||
@ -156,7 +194,6 @@ sum = (try someThrowingFunction()) + anotherThrowingFunction() // 错误:try
|
||||
> `表达式` as? `类型`
|
||||
>
|
||||
> `表达式` as! `类型`
|
||||
>
|
||||
|
||||
`is` 运算符在运行时检查表达式能否向下转化为指定的类型,如果可以则返回 `ture`,否则返回 `false`。
|
||||
|
||||
@ -196,13 +233,11 @@ f(x as Any)
|
||||
> *类型转换运算符* → **as** **?** [类型](./03_Types.md#type)
|
||||
>
|
||||
> *类型转换运算符* → **as** **!** [类型](./03_Types.md#type)
|
||||
>
|
||||
|
||||
## 基本表达式 {#primary-expressions}
|
||||
*基本表达式*是最基本的表达式。它们可以单独使用,也可以跟前缀表达式、二元表达式、后缀表达式组合使用。
|
||||
|
||||
> 基本表达式语法
|
||||
>
|
||||
|
||||
#### primary-expression {#primary-expression}
|
||||
> *基本表达式* → [标识符](./02_Lexical_Structure.md#identifier) [泛型实参子句](./09_Generic_Parameters_and_Arguments.md#generic-argument-clause)<sub>可选</sub>
|
||||
@ -224,7 +259,6 @@ f(x as Any)
|
||||
> *基本表达式* → [选择器表达式](#selector-expression)
|
||||
>
|
||||
> *基本表达式* → [key-path字符串表达式](#key-patch-string-expression)
|
||||
>
|
||||
|
||||
### 字面量表达式 {#literal-expression}
|
||||
*字面量表达式*可由普通字面量(例如字符串或者数字),字典或者数组字面量,或者下面列表中的特殊字面量组成:
|
||||
@ -261,7 +295,6 @@ myFunction() // 打印“myFunction()”
|
||||
数组字面量是值的有序集合,形式如下:
|
||||
|
||||
> [`值 1`, `值 2`, `...`]
|
||||
>
|
||||
|
||||
数组中的最后一个表达式可以紧跟一个逗号。数组字面量的类型是 `[T]`,这个 `T` 就是数组中元素的类型。如果数组中包含多种类型,`T` 则是跟这些类型最近的的公共父类型。空数组字面量由一组方括号定义,可用来创建特定类型的空数组。
|
||||
|
||||
@ -272,7 +305,6 @@ var emptyArray: [Double] = []
|
||||
字典字面量是一个包含无序键值对的集合,形式如下:
|
||||
|
||||
> [`键 1` : `值 1`, `键 2` : `值 2`, `...`]
|
||||
>
|
||||
|
||||
字典中的最后一个表达式可以紧跟一个逗号。字典字面量的类型是 `[Key : Value]`,`Key` 表示键的类型,`Value` 表示值的类型。如果字典中包含多种类型,那么 `Key` 表示的类型则为所有键最接近的公共父类型,`Value` 与之相似。一个空的字典字面量由方括号中加一个冒号组成(`[:]`),从而与空数组字面量区分开,可以使用空字典字面量来创建特定类型的字典。
|
||||
|
||||
@ -295,7 +327,6 @@ Xcode 使用 playground 字面量对程序编辑器中的颜色、文件或者
|
||||
> *字面量表达式* → [数组字面量](#array-literal) | [字典字面量](#dictionary-literal) | [练习场字面量](#playground-literal)
|
||||
>
|
||||
> *字面量表达式* → **#file** | **#filePath** | **#line** | **#column** | **#function**
|
||||
>
|
||||
|
||||
|
||||
>
|
||||
@ -351,7 +382,6 @@ Xcode 使用 playground 字面量对程序编辑器中的颜色、文件或者
|
||||
> self(`构造器参数`)
|
||||
>
|
||||
> self.init(`构造器参数`)
|
||||
>
|
||||
|
||||
如果在构造器、下标、实例方法中,`self` 引用的是当前类型的实例。在一个类型方法中,`self` 引用的是当前的类型。
|
||||
|
||||
@ -378,7 +408,6 @@ struct Point {
|
||||
```
|
||||
|
||||
> Self 表达式语法
|
||||
>
|
||||
|
||||
#### self-expression {#self-expression}
|
||||
> *self 表达式* → **self** | [self 方法表达式](#self-method-expression) | [self 下标表达式](#self-subscript-expression) | [self 构造器表达式](#self-initializer-expression)
|
||||
@ -387,15 +416,12 @@ struct Point {
|
||||
|
||||
#### self-method-expression {#self-method-expression}
|
||||
> *self 方法表达式* → **self** **.** [标识符](./02_Lexical_Structure.md#identifier)
|
||||
>
|
||||
|
||||
#### self-subscript-expression {#self-subscript-expression}
|
||||
> *self 下标表达式* → **self** **[** [函数调用参数表](#function-call-argument-list) **]**
|
||||
>
|
||||
|
||||
#### self-initializer-expression {#self-initializer-expression}
|
||||
> *self 构造器表达式* → **self** **.** **init**
|
||||
>
|
||||
|
||||
### 父类表达式 {#superclass-expression}
|
||||
*父类*表达式可以使我们在某个类中访问它的父类,它有如下形式:
|
||||
@ -405,30 +431,24 @@ struct Point {
|
||||
> super[`下标索引`]
|
||||
>
|
||||
> super.init(`构造器参数`)
|
||||
>
|
||||
|
||||
第一种形式用来访问父类的某个成员,第二种形式用来访问父类的下标,第三种形式用来访问父类的构造器。
|
||||
|
||||
子类可以通过父类表达式在它们的成员、下标和构造器中使用父类中的实现。
|
||||
|
||||
> 父类表达式语法
|
||||
>
|
||||
|
||||
#### superclass-expression {#superclass-expression}
|
||||
> *父类表达式* → [父类方法表达式](#superclass-method-expression) | [父类下标表达式](#superclass-subscript-expression) | [父类构造器表达式](#superclass-initializer-expression)
|
||||
>
|
||||
|
||||
#### superclass-method-expression {#superclass-method-expression}
|
||||
> *父类方法表达式* → **super** **.** [标识符](./02_Lexical_Structure.md#identifier)
|
||||
>
|
||||
|
||||
#### superclass-subscript-expression {#superclass-subscript-expression}
|
||||
> *父类下标表达式* → **super** [[函数调用参数表](#function-call-argument-list) **]**
|
||||
>
|
||||
|
||||
#### superclass-initializer-expression {#superclass-initializer-expression}
|
||||
> *父类构造器表达式* → **super** **.** **init**
|
||||
>
|
||||
|
||||
### 闭包表达式 {#closure-expression}
|
||||
*闭包表达式*会创建一个闭包,在其他语言中也叫 *lambda* 或*匿名*函数。跟函数一样,闭包包含了待执行的代码,不同的是闭包还会捕获所在环境中的常量和变量。它的形式如下:
|
||||
@ -530,86 +550,114 @@ myFunction { [weak parent = self.parent] in print(parent!.title) }
|
||||
关于闭包表达式的更多信息和例子,请参阅 [闭包表达式](../02_language_guide/07_Closures.md#closure-expressions)。关于捕获列表的更多信息和例子,请参阅 [解决闭包引起的循环强引用](../02_language_guide/24_Automatic_Reference_Counting.md#resolving-strong-reference-cycles-for-closures)。
|
||||
|
||||
> 闭包表达式语法
|
||||
>
|
||||
>
|
||||
>
|
||||
#### closure-expression {#closure-expression}
|
||||
>
|
||||
>
|
||||
> #### closure-expression {#closure-expression}
|
||||
>
|
||||
> *闭包表达式* → **{** [闭包签名](#closure-signature)<sub>可选</sub> [语句](#statements) **}**
|
||||
>
|
||||
>
|
||||
>
|
||||
#### closure-signature {#closure-signature}
|
||||
>
|
||||
> #### closure-signature {#closure-signature}
|
||||
>
|
||||
> *闭包签名* → [捕获列表](#capture-list)<sub>可选</sub> [闭包形参子句](#closure-parameter-clause) **throws**<sub>可选</sub> [函数结果](./06_Declarations.md#function-result)<sub>可选</sub> **in**
|
||||
>
|
||||
> 闭包签名* → [参数子句](#parameter-clause) [函数结果](./06_Declarations.md#function-result)<sub>可选</sub> **in**
|
||||
>
|
||||
> *闭包签名* → [标识符列表](#identifier-list) [函数结果](./06_Declarations.md#function-result)<sub>可选</sub> **in**
|
||||
>
|
||||
> *闭包签名* → [捕获列表](#capture-list) [参数子句](./06_Declarations.md#parameter-clause) [函数结果](./06_Declarations.md#function-result)<sub>可选</sub> **in**
|
||||
>
|
||||
> *闭包签名* → [捕获列表](#capture-list) [标识符列表](./02_Lexical_Structure.md#identifier-list) [函数结果](./06_Declarations.md#function-result)<sub>可选</sub> **in**
|
||||
>
|
||||
> *闭包签名* → [捕获列表](#capture-list) **in**
|
||||
>
|
||||
>
|
||||
>
|
||||
> #### closure-parameter-clause {#closure-parameter-clause}
|
||||
>
|
||||
#### capture-list {#capture-list}
|
||||
>
|
||||
> *闭包形参子句* → **( )**|**(**[闭包形参列表](#closure-parameter-list)**)**|[标识符列表](./02_Lexical_Structure.md#identifier-list)
|
||||
>
|
||||
> 捕获列表* → [ [捕获列表项列表](#capture-list-items) **]**
|
||||
> #### closure-parameter-list {#closure-parameter-list}
|
||||
>
|
||||
> *闭包形参列表* → [闭包形参](#closure-parameter) |[闭包形参](#closure-parameter) **,** [闭包形参列表](#closure-parameter-list)
|
||||
>
|
||||
> #### closure-parameter{#closure-parameter}
|
||||
>
|
||||
#### capture-list-items {#capture-list-items}
|
||||
> *闭包形参* → [闭包形参名字](#closure-parameter-name) [类型注解](./03_Types.md#type-annotation)<sub>可选</sub>
|
||||
>
|
||||
> *捕获列表项列表* → [捕获列表项](#capture-list-item) | [捕获列表项](#capture-list-item) **,** [捕获列表项列表](#capture-list-items)
|
||||
> *闭包形参* → [闭包形参名字](#closure-parameter-name) [类型注解](./03_Types.md#type-annotation) **...**
|
||||
>
|
||||
> #### closure-parameter-name{#closure-parameter-name}
|
||||
>
|
||||
#### capture-list-item {#capture-list-item}
|
||||
> *闭包形参名字* → [标识符](./02_Lexical_Structure.md#identifier)
|
||||
>
|
||||
> #### closure-list{#closure-list}
|
||||
>
|
||||
> *捕获列表项* → [捕获说明符](#capture-specifier)<sub>可选</sub> [表达式](#expression)
|
||||
> *捕获列表* → **[** [捕获列表项列表](#capture-list-items) **]**
|
||||
>
|
||||
>#### capture-list-items {#capture-list-items}
|
||||
>
|
||||
#### capture-specifier {#capture-specifier}
|
||||
>*捕获列表项列表* → [捕获列表项](#capture-list-item) | [捕获列表项](#capture-list-item) **,** [捕获列表项列表](#capture-list-items)
|
||||
>
|
||||
> *捕获说明符* → **weak** | **unowned** | **unowned(safe)** | **unowned(unsafe)**
|
||||
>#### capture-list-item {#capture-list-item}
|
||||
>
|
||||
>*捕获列表项* → [捕获说明符](#capture-specifier)<sub>可选</sub> [标识符](./02_Lexical_Structure.md#identifier)
|
||||
>
|
||||
> *捕获列表项* → [捕获说明符](#capture-specifier)<sub>可选</sub> [标识符](./02_Lexical_Structure.md#identifier) **=** [表达式](#expression)
|
||||
>
|
||||
> *捕获列表项* → [捕获说明符](#capture-specifier)<sub>可选</sub> [标识符](./02_Lexical_Structure.md#identifier) [Self 表达式](##self-expression)
|
||||
>
|
||||
>#### capture-specifier {#capture-specifier}
|
||||
>
|
||||
>*捕获说明符* → **weak** | **unowned** | **unowned(safe)** | **unowned(unsafe)**
|
||||
|
||||
### 隐式成员表达式 {#implicit-member-expression}
|
||||
若类型可被推断出来,可以使用*隐式成员表达式*来访问某个类型的成员(例如某个枚举成员或某个类型方法),形式如下:
|
||||
|
||||
> .`成员名称`
|
||||
>
|
||||
|
||||
例如:
|
||||
|
||||
```swift
|
||||
var x = MyEnumeration.SomeValue
|
||||
x = .AnotherValue
|
||||
var x = MyEnumeration.someValue
|
||||
x = .anotherValue
|
||||
```
|
||||
|
||||
如果推断的是可选类型,可以在隐式成员表达式里使用不可选类型的成员。
|
||||
|
||||
```swift
|
||||
var someOptional: MyEnumeration? = .someValue
|
||||
```
|
||||
|
||||
隐式成员表达式可以跟在后缀运算符或者其他在 [后缀表达式](#postfix-expressions) 里介绍的语法后面。这被称为 *链式隐式成员表达式*。尽管链式后缀表达式大多都是相同类型,但其实只需要整个链式成员表达式可以转换为上下文的类型就行了。更具体的,如果隐式类型是可选的,则可以使用非可选类型的值,如果隐式类型是类类型,则可以使用其子类的值。例如:
|
||||
|
||||
```swift
|
||||
class SomeClass {
|
||||
static var shared = SomeClass()
|
||||
static var sharedSubclass = SomeSubclass()
|
||||
var a = AnotherClass()
|
||||
}
|
||||
class SomeSubclass: SomeClass { }
|
||||
class AnotherClass {
|
||||
static var s = SomeClass()
|
||||
func f() -> SomeClass { return AnotherClass.s }
|
||||
}
|
||||
let x: SomeClass = .shared.a.f()
|
||||
let y: SomeClass? = .shared
|
||||
let z: SomeClass = .sharedSubclass
|
||||
```
|
||||
|
||||
上面的代码中,`x` 的类型和上下文的隐式类型完全匹配,`y` 的类型是从 `SomeClass` 转换成 `SomeClass?`,`z` 的类型是从 `SomeSubclass` 转换成 `SomeClass`。
|
||||
|
||||
|
||||
> 隐式成员表达式语法
|
||||
>
|
||||
|
||||
#### implicit-member-expression {#implicit-member-expression}
|
||||
> *隐式成员表达式* → **.** [标识符](./02_Lexical_Structure.md#identifier)
|
||||
>
|
||||
|
||||
### 圆括号表达式 {#parenthesized-expression}
|
||||
*圆括号表达式*是由圆括号包围的表达式。你可以用圆括号说明成组的表达式的先后操作。成组的圆括号不会改变表达式的类型 - 例如 `(1)` 的类型就是简单的 `Int`。
|
||||
|
||||
> 圆括号表达式语法
|
||||
>
|
||||
|
||||
#### parenthesized-expression {#parenthesized-expression}
|
||||
> *圆括号表达式* → **( [表达式](#expression) )**
|
||||
>
|
||||
|
||||
### 元组表达式 {#Tuple-Expression}
|
||||
*元组表达式*由圆括号和其中多个逗号分隔的子表达式组成。每个子表达式前面可以有一个标识符,用冒号隔开。元组表达式形式如下:
|
||||
|
||||
> (`标识符 1` : `表达式 1`, `标识符 2` : `表达式 2`, `...`)
|
||||
>
|
||||
|
||||
元组表达式里的每一个标识符在表达式作用域里必须是唯一的。在嵌套的元组表达式中,同嵌套层级里的标识符也必须是唯一的。例如,`(a: 10, a: 20)` 是不合法的,因为标签 `a` 在同一层级出现了两次。然而,`(a: 10, b: (a: 1, x: 2))` 是合法的,尽管 `a` 出现了两次,但有一次在外层元组里,一次在内层元组里。
|
||||
|
||||
@ -619,23 +667,18 @@ x = .AnotherValue
|
||||
>
|
||||
>
|
||||
> 在 Swift 中,空的元组表达式和空的元组类型都写作 `()`。由于 `Void` 是 `()` 的类型别名,因此可以使用它来表示空的元组类型。虽然如此,`Void` 就像所有的类型别名一样,永远是一个类型——不能表示空的元组表达式。
|
||||
>
|
||||
|
||||
|
||||
> 元组表达式语法
|
||||
>
|
||||
|
||||
#### tuple-expression {#tuple-expression}
|
||||
> *元组表达式* → **( )** | **(**[元组元素](#tuple-element), [元组元素列表](#tuple-element-list) **)**
|
||||
>
|
||||
|
||||
#### tuple-element-list {#tuple-element-list}
|
||||
> *元组元素列表* → [元组元素](#tuple-element) | [元组元素](#tuple-element) **,** [元组元素列表](#tuple-element-list)
|
||||
>
|
||||
|
||||
#### tuple-element {#tuple-element}
|
||||
> *元组元素* → [表达式](#expression) | [标识符](#identifier) **:** [表达式](#expression)
|
||||
>
|
||||
|
||||
### 通配符表达式 {#wildcard-expression}
|
||||
*通配符表达式*可以在赋值过程中显式忽略某个值。例如下面的代码中,`10` 被赋值给 `x`,而 `20` 则被忽略:
|
||||
@ -646,18 +689,15 @@ x = .AnotherValue
|
||||
```
|
||||
|
||||
> 通配符表达式语法
|
||||
>
|
||||
|
||||
#### wildcard-expression {#wildcard-expression}
|
||||
> *通配符表达式* → **_**
|
||||
>
|
||||
|
||||
|
||||
### Key-path 表达式 {#key-path-expression}
|
||||
Key-path 表达式引用一个类型的属性或下标。在动态语言中使场景可以使用 Key-path 表达式,例如观察键值对。格式为:
|
||||
|
||||
> **\类型名.路径**
|
||||
>
|
||||
|
||||
*类型名*是一个具体类型的名称,包含任何泛型参数,例如 `String`、`[Int]` 或 `Set<Int>`。
|
||||
|
||||
@ -839,7 +879,6 @@ let someTask = toDoList[keyPath: taskKeyPath]
|
||||
#### *多个 key-path 后缀* → [key-path 后缀](#key-path-postfix) [多个 key-path 后缀](#key-path-postfixes)<sub>可选<sub> key-path-postfixes {#key-path-postfixes}
|
||||
>
|
||||
> *key-path 后缀* → **?** | **!** | **self** | **\[** [函数调用参数表](#function-call-argument-list) **\]**
|
||||
>
|
||||
|
||||
|
||||
|
||||
@ -884,12 +923,10 @@ let anotherSelector = #selector(SomeClass.doSomething(-:) as (SomeClass) -> (Str
|
||||
> 注意
|
||||
>
|
||||
> 虽然方法名或者属性名是个表达式,但是它不会被求值。
|
||||
>
|
||||
|
||||
更多关于如何在 Swift 代码中使用选择器来与 Objective-C API 进行交互的信息,请参阅 [在 Swift 中使用 Objective-C 运行时特性](https://developer.apple.com/documentation/swift/using_objective_c_runtime_features_in_swift)。
|
||||
|
||||
> 选择器表达式语法
|
||||
>
|
||||
|
||||
#### selector-expression {#selector-expression}
|
||||
> *选择器表达式* → __#selector-- **(** [表达式](#expression) **)**
|
||||
@ -897,13 +934,11 @@ let anotherSelector = #selector(SomeClass.doSomething(-:) as (SomeClass) -> (Str
|
||||
> *选择器表达式* → __#selector-- **(** [getter:表达式](#expression) **)**
|
||||
>
|
||||
> *选择器表达式* → __#selector-- **(** [setter:表达式](#expression) **)**
|
||||
>
|
||||
|
||||
## Key-path 字符串表达式 {#key-path-string-expressions}
|
||||
key-path 字符串表达式可以访问一个引用 Objective-C 属性的字符串,通常在 key-value 编程和 key-value 观察 APIs 中使用。其格式如下:
|
||||
|
||||
> `#keyPath` ( `属性名` )
|
||||
>
|
||||
|
||||
属性名必须是一个可以在 Objective-C 运行时使用的属性的引用。在编译期,key-path 字符串表达式会被一个字符串字面量替换。例如:
|
||||
|
||||
@ -945,7 +980,6 @@ print(keyPath == c.getSomeKeyPath())
|
||||
>
|
||||
>
|
||||
> 尽管*属性名*是一个表达式,但它永远不会被求值
|
||||
>
|
||||
|
||||
> key-path 字符串表达式语法
|
||||
>
|
||||
@ -953,7 +987,6 @@ print(keyPath == c.getSomeKeyPath())
|
||||
#### key-path-string-expression {#key-path-string-expression}
|
||||
>
|
||||
> *key-path 字符串表达式* → **#keyPath (** [表达式](#expression) **)**
|
||||
>
|
||||
|
||||
## 后缀表达式 {#postfix-expressions}
|
||||
*后缀表达式*就是在某个表达式的后面运用后缀运算符或其他后缀语法。从语法构成上来看,基本表达式也是后缀表达式。
|
||||
@ -963,7 +996,6 @@ print(keyPath == c.getSomeKeyPath())
|
||||
关于 Swift 标准库提供的运算符的更多信息,请参阅 [运算符定义](https://developer.apple.com/documentation/swift/operator_declarations)。
|
||||
|
||||
> 后缀表达式语法
|
||||
>
|
||||
|
||||
#### postfix-expression {#postfix-expression}
|
||||
> *后缀表达式* → [基本表达式](#primary-expression)
|
||||
@ -985,21 +1017,19 @@ print(keyPath == c.getSomeKeyPath())
|
||||
> *后缀表达式* → [强制取值表达式](#forced-value-expression)
|
||||
>
|
||||
> *后缀表达式* → [可选链表达式](#optional-chaining-expression)
|
||||
>
|
||||
|
||||
### 函数调用表达式 {#function-call-expression}
|
||||
*函数调用表达式*由函数名和参数列表组成,形式如下:
|
||||
*函数调用表达式*由函数名和在括号里以逗号分隔的参数列表组成。函数调用表达式形式如下:
|
||||
|
||||
> `函数名`(`参数 1`, `参数 2`)
|
||||
>
|
||||
|
||||
函数名可以是值为函数类型的任意表达式。
|
||||
|
||||
如果函数声明中指定了参数的名字,那么在调用的时候也必须得写出来。这种函数调用表达式具有以下形式:
|
||||
如果函数声明中指定了形参的名字,那么在调用的时候也必须得写出来,并通过冒号(`:`)分隔。这种函数调用表达式具有以下形式:
|
||||
|
||||
> `函数名`(`参数名 1`: `参数 1`, `参数名 2`: `参数 2`)
|
||||
|
||||
如果函数的最后一个参数是函数类型,可以在函数调用表达式的尾部(右圆括号之后)加上一个闭包,该闭包会作为函数的最后一个参数。如下两种写法是等价的:
|
||||
函数调用表达式可以在函数调用表达式的尾部(右圆括号之后)加上多个尾随闭包,该闭包会作为函数的实参,在括号中最后一个实参后面添加。第一个闭包表达式时没有实参签名的,其他任意闭包表达式签名都有实参标签。如下两种写法是等价的,区别在是否使用尾随闭包语法:
|
||||
|
||||
```swift
|
||||
// someFunction 接受整型和闭包的实参
|
||||
@ -1011,7 +1041,7 @@ anotherFunction(x: x, f: { $0 == 13 }, g: { print(99) })
|
||||
anotherFunction(x: x) { $0 == 13 } g: { print(99) }
|
||||
```
|
||||
|
||||
如果闭包是该函数的唯一参数,那么圆括号可以省略。
|
||||
如果闭包是该函数的唯一实参,那么圆括号可以省略。
|
||||
|
||||
```swift
|
||||
// someFunction 只接受一个闭包参数
|
||||
@ -1019,49 +1049,118 @@ myData.someMethod() {$0 == 13}
|
||||
myData.someMethod {$0 == 13}
|
||||
```
|
||||
|
||||
为了支持实参中的尾随闭包,编译器从左到右检查形参列表,如下所示:
|
||||
|
||||
| 尾随闭包 | 形参 | 行为 |
|
||||
| -------- | -------------- | ------------------------------------------------------------ |
|
||||
| 有标签 | 有标签 | 如果标签相同,闭包和形参匹配,否则跳过该形参 |
|
||||
| 有标签 | 无标签 | 跳过该形参 |
|
||||
| 无标签 | 有标签或无标签 | 如果形参在结构上类似于下面定义的函数类型,和闭包匹配,否则跳过该形参 |
|
||||
|
||||
尾随闭包作为其匹配形参的实参传递。
|
||||
|
||||
在扫描过程被跳过的形参不传递实参——例如,它们使用的是默认形参。当匹配后,扫描会继续下一个尾随闭包和形参。匹配过程结束后,所有的尾随闭包必须有对应的匹配。
|
||||
|
||||
如果形参不是输入输出参数,并且类似下面的情况,则算是*结构上类似*函数类型:
|
||||
|
||||
* 函数类型的形参,例如 `(Bool) -> Int`
|
||||
* 函数类型表达式的自动闭包形参,例如 `@autoclosure () -> ((Bool) -> Int)`
|
||||
* 元素是函数类型的可变参数,例如 `((Bool) -> Int)...`
|
||||
* 单层或多层可选类型的形参,例如 `Optional<(Bool) -> Int>`
|
||||
* 由上面这些类型组合而成的形参,例如 `(Optional<(Bool) -> Int>)...`
|
||||
|
||||
尾随闭包和结构上类似函数类型的形参匹配,但它并不是函数,所以闭包会按需包装。例如,如果形参类是是可选类型,闭包会自动包装成 `Optional`。
|
||||
|
||||
为了简化 Swift 5.3 之前版本(从右到左匹配)的代码迁移 —— 编译器会同时检查从左到右和从右到左的顺序。如果不同的扫描方向产生了不同的结果,编译器则使用旧的从右到左的顺序,并生成警告。Swift 的未来版本将都使用从左到右的顺序。
|
||||
|
||||
```swift
|
||||
typealias Callback = (Int) -> Int
|
||||
func someFunction(firstClosure: Callback? = nil,
|
||||
secondClosure: Callback? = nil) {
|
||||
let first = firstClosure?(10)
|
||||
let second = secondClosure?(20)
|
||||
print(first ?? "-", second ?? "-")
|
||||
}
|
||||
|
||||
someFunction() // 打印 "- -"
|
||||
someFunction { return $0 + 100 } // 歧义
|
||||
someFunction { return $0 } secondClosure: { return $0 } // 打印 "10 20"
|
||||
```
|
||||
|
||||
在上面的例子中,Swift 5.3 中被标记为“歧义”的函数调用会打印”- 120“并产生一个编辑器警告。未来版本的 Swift 会打印”110 -“。
|
||||
|
||||
如 [特殊名称方法](./06_Declarations.md#methods-with-special-names) 所述,通过声明几种方法中的一种,类、结构体或枚举类型可以为函数调用语法启用语法糖。
|
||||
|
||||
### 指针类型的隐式转换{#implicit-conversion-to-a-pointer}
|
||||
|
||||
在函数调用表达式里,如果实参和形参的类型不一致,编译器会尝试通过下面的规则进行隐式转换来匹配类型:
|
||||
|
||||
* 输入输出的 `SomeType` 可以转换为 `UnsafePointer<SomeType>` 或者 `UnsafeMutablePointer<SomeType>`
|
||||
* 输入输出的 `Array<SomeType>` 可以转换为 `UnsafePointer<SomeType>` 或者 `UnsafeMutablePointer<SomeType>`
|
||||
* `Array<SomeType>` 可以转换为 `UnsafePointer<SomeType>`
|
||||
* `String` 可以转换为 `UnsafePointer<CChar>`
|
||||
|
||||
下面两个函数调用是等价的:
|
||||
|
||||
```swift
|
||||
func unsafeFunction(pointer: UnsafePointer<Int>) {
|
||||
// ...
|
||||
}
|
||||
var myNumber = 1234
|
||||
|
||||
unsafeFunction(pointer: &myNumber)
|
||||
withUnsafePointer(to: myNumber) { unsafeFunction(pointer: $0) }
|
||||
```
|
||||
|
||||
隐式转换创建的指针仅在函数调用期间有效。为了避免发生未定义行为,确保代码在函数调用结束后没有继续持有这些指针。
|
||||
|
||||
> 注意
|
||||
>
|
||||
> 当将数组隐式转换为不安全指针时,Swift 会按需转换或复制数组来确保数组的存储是连续的。例如,可以用此语法将没有约定存储 API 的 `NSArray` 子类桥接到 `Array` 的数组。如果能确保数组的存储是连续的,就不需要隐式转换来做这个工作,这种情况下可以用 `ContiguousArray` 代替 `Array`。
|
||||
|
||||
使用 `&` 代替类似 `withUnsafePointer(to:)` 的显式函数可以在调用底层 C 函数的可读性更高,特别是当函数传入多个指针实参时。如果是其他 Swift 代码调用函数,避免使用 `&` 代替显式的不安全 API。
|
||||
|
||||
> 函数调用表达式语法
|
||||
>
|
||||
>
|
||||
#### function-call-expression {#function-call-expression}
|
||||
>
|
||||
>
|
||||
>
|
||||
> #### function-call-expression {#function-call-expression}
|
||||
>
|
||||
> *函数调用表达式* → [后缀表达式](#postfix-expression) [函数调用参数子句](#function-call-argument-clause)
|
||||
>
|
||||
>
|
||||
> *函数调用表达式* → [后缀表达式](#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) | [函数调用参数](#function-call-argument) **,** [*函数调用参数表*](#function-call-argument-list)
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
> #### function-call-argument {#function-call-argument}
|
||||
>
|
||||
>
|
||||
> *函数调用参数* → [表达式](#expression) | [标识符](./02_Lexical_Structure.md#identifier) **:** [表达式](#expression)
|
||||
>
|
||||
>
|
||||
> *函数调用参数* → [运算符](./02_Lexical_Structure.md#operator) | [标识符](./02_Lexical_Structure.md#identifier) **:** [运算符](./02_Lexical_Structure.md#operator)
|
||||
>
|
||||
>
|
||||
> #### trailing-closure {#trailing-closure}
|
||||
>
|
||||
> *尾随闭包* → [闭包表达式](#closure-expression)
|
||||
>
|
||||
> *尾随闭包* → [闭包表达式](#closure-expression) [标签尾随闭包集](#labeled-trailing-closures)<sub>可选</sub>
|
||||
>
|
||||
> #### 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}
|
||||
|
||||
*构造器表达式*用于访问某个类型的构造器,形式如下:
|
||||
|
||||
> `表达式`.init(`构造器参数`)
|
||||
>
|
||||
|
||||
你可以在函数调用表达式中使用构造器表达式来初始化某个类型的新实例。也可以使用构造器表达式来代理给父类构造器。
|
||||
|
||||
@ -1095,19 +1194,16 @@ let s3 = someValue.dynamicType.init(data: 7) // 有效
|
||||
```
|
||||
|
||||
> 构造器表达式语法
|
||||
>
|
||||
|
||||
#### initializer-expression {#initializer-expression}
|
||||
> *构造器表达式* → [后缀表达式](#postfix-expression) **.** **init**
|
||||
>
|
||||
> *构造器表达式* → [后缀表达式](#postfix-expression) **.** **init** **(** [参数名称](#argument-names) **)**
|
||||
>
|
||||
|
||||
### 显式成员表达式 {#explicit-member-expression}
|
||||
*显式成员表达式*允许我们访问命名类型、元组或者模块的成员,其形式如下:
|
||||
|
||||
> `表达式`.`成员名`
|
||||
>
|
||||
|
||||
命名类型的某个成员在原始实现或者扩展中定义,例如:
|
||||
|
||||
@ -1160,7 +1256,6 @@ let x = [10, 3, 20, 15, 4]
|
||||
```
|
||||
|
||||
> 显式成员表达式语法
|
||||
>
|
||||
|
||||
#### explicit-member-expression {#explicit-member-expression}
|
||||
> *显式成员表达式* → [后缀表达式](#postfix-expression) **.** [十进制数字](./02_Lexical_Structure.md#decimal-digit)
|
||||
@ -1174,7 +1269,6 @@ let x = [10, 3, 20, 15, 4]
|
||||
|
||||
#### argument-name {#argument-name}
|
||||
> *参数名* → [标识符](./02_Lexical_Structure.md#identifier) **:**
|
||||
>
|
||||
|
||||
### 后缀 self 表达式 {#postfix-self-expression}
|
||||
后缀 `self` 表达式由某个表达式或类型名紧跟 `.self` 组成,其形式如下:
|
||||
@ -1182,42 +1276,35 @@ let x = [10, 3, 20, 15, 4]
|
||||
> `表达式`.self
|
||||
>
|
||||
> `类型`.self
|
||||
>
|
||||
|
||||
第一种形式返回表达式的值。例如:`x.self` 返回 `x`。
|
||||
|
||||
第二种形式返回相应的类型。我们可以用它来获取某个实例的类型作为一个值来使用。例如,`SomeClass.self` 会返回 `SomeClass` 类型本身,你可以将其传递给相应函数或者方法作为参数。
|
||||
|
||||
> 后缀 self 表达式语法
|
||||
>
|
||||
|
||||
#### postfix-self-expression {#postfix-self-expression}
|
||||
> *后缀 self 表达式* → [后缀表达式](#postfix-expression) **.** **self**
|
||||
>
|
||||
|
||||
|
||||
### 下标表达式 {#subscript-expression}
|
||||
可通过*下标表达式*访问相应的下标,形式如下:
|
||||
|
||||
> `表达式`[`索引表达式`]
|
||||
>
|
||||
|
||||
要获取下标表达式的值,可将索引表达式作为下标表达式的参数来调用下标 getter。下标 setter 的调用方式与之一样。
|
||||
|
||||
关于下标的声明,请参阅 [协议下标声明](./06_Declarations.md#protocol-subscript-declaration)。
|
||||
|
||||
> 下标表达式语法
|
||||
>
|
||||
|
||||
#### subscript-expression {#subscript-expression}
|
||||
> *下标表达式* → [后缀表达式](#postfix-expression) **[** [表达式列表](#expression-list) **]**
|
||||
>
|
||||
|
||||
### 强制取值表达式 {#forced-Value-expression}
|
||||
当你确定可选值不是 `nil` 时,可以使用*强制取值表达式*来强制解包,形式如下:
|
||||
|
||||
> `表达式`!
|
||||
>
|
||||
|
||||
如果该表达式的值不是 `nil`,则返回解包后的值。否则,抛出运行时错误。
|
||||
|
||||
@ -1234,17 +1321,14 @@ someDictionary["a"]![0] = 100
|
||||
```
|
||||
|
||||
> 强制取值语法
|
||||
>
|
||||
|
||||
#### forced-value-expression {#forced-value-expression}
|
||||
> *强制取值表达式* → [后缀表达式](#postfix-expression) **!**
|
||||
>
|
||||
|
||||
### 可选链表达式 {#optional-chaining-expression}
|
||||
*可选链表达式*提供了一种使用可选值的便捷方法,形式如下:
|
||||
|
||||
> `表达式`?
|
||||
>
|
||||
|
||||
后缀 `?` 运算符会根据表达式生成可选链表达式而不会改变表达式的值。
|
||||
|
||||
@ -1286,7 +1370,6 @@ someDictionary["a"]?[0] = someFunctionWithSideEffects()
|
||||
```
|
||||
|
||||
> 可选链表达式语法
|
||||
>
|
||||
|
||||
#### optional-chaining-expression {#optional-chaining-expression}
|
||||
> *可选链表达式* → [后缀表达式](#postfix-expression) **?**
|
||||
|
||||
@ -43,7 +43,6 @@
|
||||
> *循环语句* → [while 语句](#while-statement)
|
||||
>
|
||||
> *循环语句* → [repeat-while 语句](#repeat-while-statement)
|
||||
>
|
||||
|
||||
### For-In 语句 {#for-in-statements}
|
||||
|
||||
@ -65,7 +64,6 @@ for item in collection {
|
||||
|
||||
#### for-in-statement {#for-in-statement}
|
||||
> *for-in 语句* → **for** **case**<sub>可选</sub> [模式](./08_Patterns.md#pattern) **in** [表达式](./04_Expressions.md#expression) [where 子句](#where-clause)<sub>可选</sub> [代码块](./06_Declarations.md#code-block)
|
||||
>
|
||||
|
||||
### While 语句 {#while-statements}
|
||||
只要循环条件为真,`while` 语句就会重复执行代码块。
|
||||
@ -93,12 +91,10 @@ while condition {
|
||||
|
||||
#### while-statement {#while-statement}
|
||||
> *while 语句* → **while** [条件子句](#condition-clause) [代码块](./06_Declarations.md#code-block)
|
||||
>
|
||||
|
||||
|
||||
#### condition-clause {#condition-clause}
|
||||
> *条件子句* → [表达式](./04_Expressions.md#expression) | [表达式](./04_Expressions.md#expression) **,** [条件列表](#condition-list)
|
||||
>
|
||||
|
||||
#### condition {#condition}
|
||||
> *条件* → [表达式](./04_Expressions.md#expression) |[可用性条件](#availability-condition) | [case 条件](#case-condition) | [可选绑定条件](#optional-binding-condition)
|
||||
@ -107,11 +103,9 @@ while condition {
|
||||
|
||||
#### case-condition {#case-condition}
|
||||
> *case 条件* → **case** [模式](./08_Patterns.md#pattern) [构造器](./06_Declarations.md#initializer)
|
||||
>
|
||||
|
||||
#### optional-binding-condition {#optional-binding-condition}
|
||||
> *可选绑定条件* → **let** [模式](./08_Patterns.md#pattern) [构造器](./06_Declarations.md#initializer) | **var** [模式](./08_Patterns.md#pattern) [构造器](./06_Declarations.md#initializer)
|
||||
>
|
||||
|
||||
### Repeat-While 语句 {#repeat-while-statements}
|
||||
`repeat-while` 语句至少执行一次代码块,之后只要循环条件为真,就会重复执行代码块。
|
||||
@ -139,7 +133,6 @@ repeat {
|
||||
|
||||
#### repeat-while-statement {#repeat-while-statement}
|
||||
> *repeat-while 语句* → **repeat** [代码块](./06_Declarations.md#code-block) **while** [表达式](./04_Expressions.md#expression)
|
||||
>
|
||||
|
||||
## 分支语句 {#branch-statements}
|
||||
分支语句会根据一个或者多个条件来执行指定部分的代码。分支语句中的条件将会决定程序如何分支以及执行哪部分代码。Swift 提供三种类型的分支语句:`if` 语句、 `guard` 语句和 `switch` 语句。
|
||||
@ -156,7 +149,6 @@ repeat {
|
||||
> *分支语句* → [guard 语句](#guard-statement)
|
||||
>
|
||||
> *分支语句* → [switch 语句](#switch-statement)
|
||||
>
|
||||
|
||||
### If 语句 {#if-statements}
|
||||
`if` 语句会根据一个或多个条件来决定执行哪一块代码。
|
||||
@ -201,7 +193,6 @@ if condition 1 {
|
||||
|
||||
#### if-statement {#if-statement}
|
||||
> *if 语句* → **if** [条件子句](#condition-clause) [代码块](./06_Declarations.md#code-block) [else 子句](#else-clause)<sub>可选</sub>
|
||||
>
|
||||
|
||||
#### else-clause {#else-clause}
|
||||
> *else 子句* → **else** [代码块](./06_Declarations.md#code-block) | **else** [if 语句](#if-statement)
|
||||
@ -309,24 +300,19 @@ case .suppressed:
|
||||
|
||||
#### switch-statement {#switch-statement}
|
||||
> *switch 语句* → **switch** [表达式](./04_Expressions.md#expression) **{** [switch-case 列表](#switch-cases)<sub>可选</sub> **}**
|
||||
>
|
||||
|
||||
#### switch-cases {#switch-cases}
|
||||
> *switch case 列表* → [switch-case](#switch-case) [switch-case 列表](#switch-cases)<sub>可选</sub>
|
||||
>
|
||||
|
||||
#### switch-case {#switch-case}
|
||||
> *switch case* → [case 标签](#case-label) [多条语句](#statements) | [default 标签](#default-label) [多条语句](#statements) | [conditional-switch-case](#conditional-switch-case-label)
|
||||
>
|
||||
|
||||
|
||||
#### case-label {#case-label}
|
||||
> *case 标签* → [属性](#switch-case-attributes-label)<sub>可选</sub> **case** [case 项列表](#case-item-list) **:**
|
||||
>
|
||||
|
||||
#### case-item-list {#case-item-list}
|
||||
> *case 项列表* → [模式](./08_Patterns.md#pattern) [where 子句](#where-clause)<sub>可选</sub> | [模式](./08_Patterns.md#pattern) [where 子句](#where-clause)<sub>可选</sub> **,** [case 项列表](#case-item-list)
|
||||
>
|
||||
|
||||
#### default-label {#default-label}
|
||||
> *default 标签* → [属性](#switch-case-attributes-label)<sub>可选</sub> **default** **:**
|
||||
@ -335,7 +321,6 @@ case .suppressed:
|
||||
|
||||
#### where-clause {#where-clause}
|
||||
> *where-clause* → **where** [where 表达式](#where-expression)
|
||||
>
|
||||
|
||||
#### where-expression {#where-expression}
|
||||
> *where-expression* → [表达式](./04_Expressions.md#expression)
|
||||
@ -344,23 +329,18 @@ case .suppressed:
|
||||
|
||||
#### grammar-conditional-switch-case {#grammar-conditional-switch-case}
|
||||
> *conditional-switch-case* → [switch-if-directive-clause](#switch-case-attributes-label) [switch-elseif-directive-clauses](#switch-case-attributes-label) <sub>可选</sub> [switch-else-directive-clause](#switch-case-attributes-label) <sub>可选</sub> [endif-directive](#switch-case-attributes-label)
|
||||
>
|
||||
|
||||
#### grammar-switch-if-directive-clause {#grammar-switch-if-directive-clause}
|
||||
> *switch-if-directive 语句* → [if-directive](#switch-case-attributes-label) [compilation-condition](#switch-case-attributes-label) [switch-cases](#switch-case-attributes-label) <sub>可选</sub>
|
||||
>
|
||||
|
||||
#### grammar-switch-elseif-directive-clauses {#grammar-switch-elseif-directive-clauses}
|
||||
> *switch-elseif-directive 语句(复数)* → [elseif-directive-clause](#switch-case-attributes-label) [switch-elseif-directive-clauses](#switch-case-attributes-label)<sub>可选</sub>
|
||||
>
|
||||
|
||||
#### grammar-switch-elseif-directive-clause {#grammar-switch-elseif-directive-clause}
|
||||
> *switch-elseif-directive 语句* → [elseif-directive](#switch-case-attributes-label) [compilation-condition](#switch-case-attributes-label) [switch-cases](#switch-case-attributes-label)<sub>可选</sub>
|
||||
>
|
||||
|
||||
#### grammar-switch-else-directive-clause {#grammar-switch-else-directive-clause}
|
||||
> *switch-else-directive 语句* → [else-directive](#switch-case-attributes-label) [switch-cases](#switch-case-attributes-label) <sub>可选</sub>
|
||||
>
|
||||
|
||||
## 带标签的语句 {#labeled-statements}
|
||||
你可以在循环语句或 `switch` 语句前面加上标签,它由标签名和紧随其后的冒号(`:`)组成。在 `break` 和 `continue` 后面跟上标签名可以显式地在循环语句或 `switch` 语句中改变相应的控制流。关于这两条语句用法,请参阅 [Break 语句](#break-statement) 和 [Continue 语句](#continue-statement)。
|
||||
@ -381,15 +361,12 @@ case .suppressed:
|
||||
> *带标签的语句* → [语句标签](#statement-label) [switch 语句](#switch-statement)
|
||||
>
|
||||
> > *带标签的语句* → [语句标签](#statement-label) [do 语句](#sdo-statement)
|
||||
>
|
||||
|
||||
#### statement-label {#statement-label}
|
||||
> *语句标签* → [标签名称](#label-name) **:**
|
||||
>
|
||||
|
||||
#### label-name {#label-name}
|
||||
> *标签名称* → [标识符](./02_Lexical_Structure.md#identifier)
|
||||
>
|
||||
|
||||
## 控制转移语句 {#control-transfer-statements}
|
||||
控制转移语句能够无条件地把控制权从一片代码转移到另一片代码,从而改变代码执行的顺序。Swift 提供五种类型的控制转移语句:`break` 语句、`continue` 语句、`fallthrough` 语句、`return` 语句和 `throw` 语句。
|
||||
@ -408,7 +385,6 @@ case .suppressed:
|
||||
> *控制转移语句* → [return 语句](#return-statement)
|
||||
>
|
||||
> *控制转移语句* → [throw 语句](#throw-statement)
|
||||
>
|
||||
|
||||
### Break 语句 {#break-statement}
|
||||
`break` 语句用于终止循环语句、`if` 语句或 `switch` 语句的执行。使用 `break` 语句时,可以只写 `break` 这个关键词,也可以在 `break` 后面跟上标签名,像下面这样:
|
||||
@ -416,7 +392,6 @@ case .suppressed:
|
||||
> break
|
||||
>
|
||||
> break `label name`
|
||||
>
|
||||
|
||||
当 `break` 语句后面带标签名时,可用于终止由这个标签标记的循环语句、`if` 语句或 `switch` 语句的执行。
|
||||
|
||||
@ -432,7 +407,6 @@ case .suppressed:
|
||||
|
||||
#### break-statement {#break-statement}
|
||||
> *break 语句* → **break** [标签名称](#label-name)<sub>可选</sub>
|
||||
>
|
||||
|
||||
### Continue 语句 {#continue-statement}
|
||||
`continue` 语句用于终止循环中当前迭代的执行,但不会终止该循环的执行。使用 `continue` 语句时,可以只写 `continue` 这个关键词,也可以在 `continue` 后面跟上标签名,像下面这样:
|
||||
@ -440,7 +414,6 @@ case .suppressed:
|
||||
> continue
|
||||
>
|
||||
> continue `label name`
|
||||
>
|
||||
|
||||
当 `continue` 语句后面带标签名时,可用于终止由这个标签标记的循环中当前迭代的执行。
|
||||
|
||||
@ -458,7 +431,6 @@ case .suppressed:
|
||||
|
||||
#### continue-statement {#continue-statement}
|
||||
> *continue 语句* → **continue** [标签名称](#label-name)<sub>可选</sub>
|
||||
>
|
||||
|
||||
### Fallthrough 语句 {#fallthrough-statements}
|
||||
`fallthrough` 语句用于在 `switch` 语句中转移控制权。`fallthrough` 语句会把控制权从 `switch` 语句中的一个 `case` 转移到下一个 `case`。这种控制权转移是无条件的,即使下一个 `case` 的模式与 `switch` 语句的控制表达式的值不匹配。
|
||||
@ -473,7 +445,6 @@ case .suppressed:
|
||||
|
||||
#### fallthrough-statement {#fallthrough-statement}
|
||||
> *fallthrough 语句* → **fallthrough**
|
||||
>
|
||||
|
||||
### Return 语句 {#return-statements}
|
||||
`return` 语句用于在函数或方法的实现中将控制权转移到调用函数或方法,接着程序将会从调用位置继续向下执行。
|
||||
@ -483,7 +454,6 @@ case .suppressed:
|
||||
> return
|
||||
>
|
||||
> return `expression`
|
||||
>
|
||||
|
||||
当 `return` 语句后面带表达式时,表达式的值将会返回给调用函数或方法。如果表达式的值的类型与函数或者方法声明的返回类型不匹配,Swift 则会在返回表达式的值之前将表达式的值的类型转换为返回类型。
|
||||
|
||||
@ -491,7 +461,6 @@ case .suppressed:
|
||||
>
|
||||
>
|
||||
> 正如 [可失败构造器](./06_Declarations.md#failable-initializers) 中所描述的,`return nil` 在可失败构造器中用于表明构造失败。
|
||||
>
|
||||
|
||||
而只写 `return` 时,仅仅是从该函数或方法中返回,而不返回任何值(也就是说,函数或方法的返回类型为 `Void` 或者说 `()`)。
|
||||
|
||||
@ -511,7 +480,6 @@ case .suppressed:
|
||||
`throw` 语句由 `throw` 关键字紧跟一个表达式组成,如下所示:
|
||||
|
||||
> throw `expression`
|
||||
>
|
||||
|
||||
表达式的结果必须符合 `ErrorType` 协议。
|
||||
|
||||
@ -523,7 +491,6 @@ case .suppressed:
|
||||
|
||||
#### throw-statement {#throw-statement}
|
||||
> *throw 语句* → **throw** [表达式](./04_Expressions.md#expression)
|
||||
>
|
||||
|
||||
## Defer 语句 {#defer-statements}
|
||||
`defer` 语句用于在退出当前作用域之前执行代码。
|
||||
@ -560,7 +527,6 @@ f()
|
||||
|
||||
#### defer-statement {#defer-statement}
|
||||
> *延迟语句* → **defer** [代码块](./06_Declarations.md#code-block)
|
||||
>
|
||||
|
||||
## Do 语句 {#do-statements}
|
||||
`do` 语句用于引入一个新的作用域,该作用域中可以含有一个或多个 `catch` 子句,`catch` 子句中定义了一些匹配错误条件的模式。`do` 语句作用域内定义的常量和变量只能在 `do` 语句作用域内使用。
|
||||
@ -600,11 +566,9 @@ do {
|
||||
|
||||
#### do-statement {#do-statement}
|
||||
> *do 语句* → **do** [代码块](./06_Declarations.md#code-block) [多条 catch 子句](#catch-clauses)<sub>可选</sub>
|
||||
>
|
||||
|
||||
#### catch-clauses {#catch-clauses}
|
||||
> *多条 catch 子句* → [catch 子句](#catch-clause) [多条 catch 子句](#catch-clauses)<sub>可选</sub>
|
||||
>
|
||||
|
||||
#### catch-clause {#catch-clause}
|
||||
> *catch 子句* → **catch** [模式](./08_Patterns.md#pattern)<sub>可选</sub> [where 子句](#where-clause)<sub>可选</sub> [代码块](./06_Declarations.md#code-block)
|
||||
@ -628,7 +592,6 @@ do {
|
||||
> *编译器控制语句* → [线路控制语句](#line-control-statement)
|
||||
>
|
||||
> *编译器控制语句* → [诊断语句](#grammar-diagnostic-statement)
|
||||
>
|
||||
|
||||
### 条件编译代码块 {#Conditional-Compilation-Block}
|
||||
|
||||
@ -727,7 +690,6 @@ statements to compile if both compilation conditions are false
|
||||
> *else-directive* → **#else**
|
||||
>
|
||||
> *endif-directive* → **#endif**
|
||||
>
|
||||
|
||||
|
||||
#### compilation-condition {#compilation-condition}
|
||||
@ -744,7 +706,6 @@ statements to compile if both compilation conditions are false
|
||||
> *编译条件* → [编译条件](#compilation-condition) **&&** [编译条件](#compilation-condition)
|
||||
>
|
||||
> *编译条件* → [编译条件](#compilation-condition) **||** [编译条件](#compilation-condition)
|
||||
>
|
||||
|
||||
|
||||
#### grammar-platform-condition {#grammar-platform-condition}
|
||||
@ -810,7 +771,6 @@ statements to compile if both compilation conditions are false
|
||||
#### line-number {#line-number}
|
||||
|
||||
> *行号* → 大于 0 的十进制整数
|
||||
>
|
||||
|
||||
#### file-name {#file-name}
|
||||
> *文件名* → [静态字符串字面量](./02_Lexical_Structure.md#static-string-literal)
|
||||
@ -828,7 +788,6 @@ statements to compile if both compilation conditions are false
|
||||
|
||||
> 编译时诊断语句语法
|
||||
>
|
||||
>
|
||||
|
||||
#### grammar-compile-time-diagnostic-statement {#grammar-compile-time-diagnostic-statement}
|
||||
> *诊断语句* → **#error** **(** [诊断消息](#grammar-diagnostic-message) **)**
|
||||
@ -859,7 +818,6 @@ if #available(platform name version, ..., *) {
|
||||
|
||||
> 可用性条件语法
|
||||
>
|
||||
>
|
||||
|
||||
#### availability-condition {#availability-condition}
|
||||
> *可用性条件* → **#available** **(** [可用性参数列表](#availability-arguments) **)**
|
||||
@ -871,8 +829,6 @@ if #available(platform name version, ..., *) {
|
||||
> *可用性参数* → [平台名称](#platform-name) [平台版本](#platform-version)
|
||||
>
|
||||
> *可用性条件* → __*__
|
||||
>
|
||||
>
|
||||
|
||||
#### platform-name {#platform-name}
|
||||
> *平台名称* → **iOS** | **iOSApplicationExtension**
|
||||
@ -882,7 +838,6 @@ if #available(platform name version, ..., *) {
|
||||
> *平台名称* → **watchOS**
|
||||
>
|
||||
> *平台名称* → **tvOS**
|
||||
>
|
||||
|
||||
#### platform-version {#platform-version}
|
||||
> *平台版本* → [十进制数字](./02_Lexical_Structure.md#decimal-digits)
|
||||
|
||||
Reference in New Issue
Block a user