语句

Swift 有三种语句: 基本语句、编译控制语句和控制流语句。 基本语句最常见,由表达式和申明组成。 编译控制语句允许程序更改编译器的行为,包括条件编译和单条控制语句。

控制流语句在程序中控制执行顺序。 Swift 中有几种控制流语句, 包括循环语句、 分支语句和控制转移语句。循环是让一段代码重复执行,分支是让满足条件的特定代码段被执行,控制转移语句提供了一种修改代码执行顺序的方式。 另外, Swift 还提供一种 do 语句执行代码段,并能捕获和处理错误,  defer 语句执行清除动作在当前代码退出执行后。

表达式后面跟的分号(;)可以不加,如果多行语句写在同一行里,它起到分割的作用。

语句语法

语句  → 表达式 ;可选

语句  → 申明 ;可选

语句  → 循环语句 ;可选

语句  → 分支语句 ;可选

语句  → 标签语句 ;可选

语句  → 控制转移语句 ;可选

语句  →  defer 语句 ;可选

语句  →  do 语句;可选

语句  → 编译控制语句

语句  → 语句语句 可选


循环语句

循环语句是依赖其特定条件,让一段代码块被重复地执行。 Swift 有三种循环语句: for-in 循环、 while 循环和 repeat-while 循环。

控制流会被 break 和 continue 语句打断。 更多相关讨论见下面 Break 语句 和 Continue 语句

循环语句语法

循环语句  → for-in 循环

循环语句  → while 循环

循环语句  → repeat-while 循环

For-In 语句

 for-in 语句让遵守了 Sequence 协议的任意集合类型中的每一项被执行一次。

 for-in 语句格式如下:

for item in collection {
    statements
}

 makeIterator() 方法可以获取一个遵守了 IteratorProtocol 协议的可迭代类型的值。循环开始时调用 next() 方法,返回值不为空 nil 的话,迭代返回值设置给上面的 item ,程序开始执行这个 statements 代码段,执行完后继续返回循环开头继续下一次上述执行。 否则,程序终止当前 for-in 循环。

for-in 循环语法

for-in 循环  → for case可选 pattern in 表达式 where 分句 可选 代码块

While 语句

当判断条件为真(true)时, while 循环让其代码段被重复执行.

 while语句如下所示:

while condition {
    statements
}

 while 循环执行过程:

  1. 条件 判断。 

    如果为真,继续下一次执行。如果为假,则程序结束当前 while 循环执行。

  2. 程序执行 表达式 , 然后返回第一步继续重复执行。

因为条件判断发生在代码段执行前,所以 while 循环可能被执行 0 次或多次。

判断条件值必须是一个 Bool 类型或可以转化为 Bool 类型的值。 条件值也可以是绑定的可选值, 见讨论 可选绑定

while 循环语法

while 语句  → while 条件列表 代码块

条件列表  → 条件 | 条件 , 条件列表

条件  → 表达式 | 有效条件 |  case 条件 | 可选绑定条件

case 条件  → case 模式 构造器

可选绑定条件  → let 模式 构造器 | var 模式 构造器

Repeat-While 语句

如果判断条件为真, repeat-while 循环将被执行 1 次或多次。

 repeat-while 循环如下所示:

repeat {
    statements
} while condition

 repeat-while 循环执行过程:

  1. 程序先执行 表达式 ,然后执行第 2 步。

  2.  条件 判断。

    如果为真 true, 返回第一步继续执行。如果为假 false ,程序终止当前 repeat-while 循环执行。

因为表达式执行发生在条件判断之前, 所以 repeat-while 循环至少执行一次。

条件 必须是一个 Bool 类型或可以转化为 Bool 类型的值。 当然也可以是可选绑定值, 见讨论 可选绑定.

a repeat-while 循环语法

repeat-while 循环  → repeat 代码段 while 表达式


Branch 语句

分支语句执行特定满足条件的一个或多个代码段。 在一个分支语句中特定条件值控制程序如何划分分支,并且哪段代码被执行。 Swift 有三个条件分支语句: if 语句、 guard 语句和 switch 语句。

在 if 语句或 switch 语句中,控制流被 break 语句改变,更多讨论见下面 Break 语句 。

分支语句语法

分支语句 → if 语句

分支语句 → guard 语句

分支语句 → switch 语句

If Statement

 if 语句中的一个或多个判断条件为真时,执行其内部的代码段。

if 语句有两种基本形式。 每种形式,都要求有一对大括号( {} )。

下面这种形式条件为真时,执行其内部的代码段:

if condition {
    statements
}

另一种 if 语句提供了一个 else 分句 ,用来执行该条件为假时的代码段。语法格式如下:

if condition {
    statements to execute if condition is true
} else {
    statements to execute if condition is false
}

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
}

 if 语句中条件值必须是 Bool 类型或可以转化为 Bool 类型的值。 当然也可以是可选绑定,见讨论 可选绑定.

if 语句语法

if 语句  → if条件列表 代码段 else 分句 可选

else 分句  → else代码段 | else if 语句

Guard 语句

 当判断条件不符合时,guard 语句用来阻止程序继续往下执行。

 guard 语句语法格式如下:

guard condition else {
    statements
}

 guard 语句中判断条件必须是一个 Bool 类型或可以转化为 Bool 类型的值。当然也可以是可选绑定值,见讨论 可选绑定

在 guard 语句中,从可选绑定的任何常量或变量可以在 guard 语句后面的作用域中被使用。

 guard 语句的 else 分句是必须的, 可以用下面中的关键词来结束,并且阻止程序穿透 guard 继续往下执行:

  • return
  • break
  • continue
  • throw

控制转移语句见讨论 控制转移语句 。 更多有关无返回值函数, 见 无返回值函数.

guard 语句语法

guard 语句  → guard 条件列表 else 代码段

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
}

 switch 语句的 控制表达式 每次会与 case 的具体值进行比较。 如果发现匹配项,则执行匹配值的代码段。 每一个 case 代码段不能为空,且 case 的冒号 (:)下面至少包含一条执行语句。 如果你不打算在匹配的情况中做任何事,可以用一个 break 语句结束执行。

划分代码的 case 表达式值是非常灵活的。除了像整数和字符这些标量类型的值外,表达式值可以是浮点数、 字符串、 元祖、 自定义类型实例或可选值等任何类型的值。控制表达式 甚至可以匹配 case 中枚举类型或包含了一段确定范围这样的值。 如何在 switch 语句中使用一系列这样值的例子,见 Switch 章节中的 控制流.

 switch 中在每一个 case 模式后面还可以包含一个 where 分句。where 分句where 关键字及后面的语句联合组成,旨在给 case 模式与控制表达式 匹配之前提供一个额外的条件。 如果 case 带有 where 分句, 该 case 中的 代码段 被执行当且仅当 控制表达式 匹配这个case 模式且 where 分句条件为真 true 。 例如下面的例子,控制表达式 匹配这个case 模式当且仅当控制表达式的值是一个元祖且这两个元素值相等,例如元祖 (1, 1)

case let (x, y) where x == y:

上面的例子中,case 模式也可以是一个用 let 绑定的可选常量值(当然也能用 var 绑定变量值)。 这些常量(或变量)值可以在后面的 where 分句或 case 模式下面的代码作用域中被使用。 如果一个case 包含多种模式来匹配控制表达式, 所有的模式必须包含相同的常量或变量绑定,并且在所有 case 模式中,每个边界的常量或变量类型必须相同。

 switch 也可以用 default 关键字来包含一个默认模式。 当其他所有 case 模式都不匹配时,就会执行默认模式中的代码段。  switch 语句只能包含一个默认模式,放在 switch 语句所有模式的最下面。

尽管在模式中真正的匹配操作顺序和特定的比较顺序没有明确规定,但在 switch 语句中模式匹配行为的顺序就是模式从上到下排列的顺序。如果匹配结果中,多个 case 模式同时匹配这个控制表达式的值, 那么程序只会执行这些相同模式中的第一个 case 的代码段。

Switch 语句必须明确

在 Swift 中,控制表达式类型的每一个可能值至少匹配一个 case 模式值。当条件不可行时(控制表达式的值是 Int 类型),你可以包含一个默认 case 来满足要求。

Case 默认不会穿透

匹配 case 的代码段被执行完毕后,程序从当前 switch 语句中退出执行。 case 不会继续或穿透到下一个 case (或默认case)中继续执行。 这意味着如果你想从一个case 执行到下一个case 时,在需要穿透的 case 代码段中,用 fallthrough 关键字明确写明。 更多有关 fallthrough 语句信息,见 Fallthrough 语句 。

switch 语句语法

switch 语句  → switch 表达式 { switch-cases 可选 }

switch-cases  → switch-case switch-cases opt

switch-case  → case语句 | default 语句

case-label  → case case 项列表 :

case-item-list  → 模式where 分句 可选 | 模式 where 分句 可选 , case 项列表

default-label  → default``:

where-clause  → wherewhere 表达式

where-expression  → 表达式


语句标签

你可以给循环语句、if 语句、 switch 语句、 或 do 语句加一个 语句标签 前缀,标签由标签名后接一个分号( : )组成。 用 break 和 continue 接标签名来明确指明你想如何在循环语句或 switch 语句中改变控制流,见讨论 Break 语句 和 Continue 语句 。

标签名表示其后面整个代码段。你可以在标签语句中嵌套标签语句,但要保证每一个标签名唯一。

有关如何使用标签语句的更多例子,见 标签语句 章节中的 控制流.

标签语句语法

标签语句 → 语句标签 循环语句

标签语句 → 语句标签 if 语句

标签语句 → 语句标签 switch 语句

标签语句 → 语句标签 do 语句

语句标签  → 标签名 :

标签名  → 标识符


控制转移语句

控制转移语句能无条件地把控制权从一块代码转移到另一块代码,进而改变代码的执行顺序。 Swift 有五种控制转移语句:  break 语句、 continue 语句、 fallthrough 语句、 return 语句和 throw 语句。

控制转移语句语法

控制转移语句  → break 语句

控制转移语句  → continue 语句

控制转移语句  → fallthrough 语句

控制转移语句  → return 语句

控制转移语句  → throw 语句

Break 语句

 break 可以终止程序的循环、 if 或 switch 语句执行。  break 语句可以单独使用, 也可以后面接语句标签组合使用,例如下面示例:

break
break label name

break 语句后面跟语句标签时,它会终止后面循环、 ifswitch 的标签命名语句代码段。

如果 break 语句单独使用,它结束当前它所在的 switch 或循环语句的执行。 你不能用它来结束一个未标记 breakif 语句。

如果需要,在循环或 switch 语句中 break 都可以控制代码当前执行位置,来转移到语句作用域的第一行执行。

有关如何使用 break 语句的例子,见 控制流 中的 Break 和 标签语句 。

break 语句语法

break 语句  → break 标签名 可选

Continue 语句

 continue 语句结束循环中当前迭代项的执行,但不会结束整个循环。  continue 可以单独使用,或在其后面跟语句标签使用,例如下面。

continue
continue label name

如果 continue 后面接语句标签, 他结束当前项中该标签语句表示的代码段的执行。

如果 continue 单独使用, 它隐式地跳过循环语句的当前项,进入一下项迭代执行。

这两种情况相同,程序都会控制转移到循环语句的执行条件。

对于 for 循环, continue 语句后面的增加的表达式仍然会被执行,因其在循环体执行之后执行。

有关如何使用 continue 语句的例子, 见 控制流 中的 Continue 和 标签语句

continue 语句语法

continue 语句  → continue 标签名 可选

Fallthrough 语句

fallthrough 语句的 fallthrough 关键字仅仅出现在 switch 语句的 case 代码段中。  fallthrough 语句让程序从一个 case 代码段穿透到下一个 case 代码段中继续执行。即使这个 case 模式值和 switch 控制表达式不匹配,程序也会继续执行。

 fallthrough 语句可以写在 switch 关键字任何地方, 但不能在最后一个 case 中使用。 并且它也不能从一个 case 代码段中转移到下一个是可选值绑定模式的 case 中。

一个有关如何使用 fallthrough 的例子, 见 控制流 中的 控制转移语句

fallthrough 语句语法

fallthrough 语句  → fallthrough

Return 语句

 return 语句出现在函数体内或方法定义的最后一行,返回当前函数或方法的执行结果。 程序会立即执行函数或方法在该调用位置。

 return 语句可以单独使用,也可以在其后面跟一个表达式,例如下面示例:

return
return expression

如果 return 后面跟表达式,该表达式的值将会伴随函数或方法的调用返回。如果表达式值的类型和函数或方法申明的返回类型不匹配,则会将该值自动转换为返回类型给函数或方法的调用者。

注意

可失败构造器 中描述一种在失败构造器中特殊形式的 return 语句(返回空)被用来表示初始化失败的例子。

如果 return 语句后面不跟表达式,它表示从一个函数或方法返回没有返回值(意味着函数的返回类型为 Void 或 ())。

return 语句语法

return 语句  → return 表达式 可选

Throw 语句

 throw 语句出现在可抛出错误的函数或方法体内,或类型被 throws 关键字标记的分句表达式中。

 throw 语句使程序结束当前作用域的执行,并在作用域中开始错误传递。 这个被抛出的错误继续传递直到它被 do 语句的 catch 分句处理。

一条 throw 语句由 throw 关键字后跟一个表达式组成,例如下面:

throw expression

 表达式 值的类型必须遵守 Error协议。

一个有关如何使用 throw 语句的例子, 见 错误处理 中的 用可抛出错误函数传递错误  。

throw 语句语法

throw 语句  → throw 表达式


Defer 语句

程序控制将要转移出当前 defer 语句的作用域时,这个 defer 语句将被执行。

 defer 语句格式如下:

defer {
    statements
}

无论程序控制如何被转移,在 defer 中的语句都会被执行。 举个例子,这意味着 defer 语句能被用来执行手动资源管理例如关闭文件句柄,或当有错误抛出时执行一些操作。

如果多条 defer 语句出现在同一作用域中时,他们的出现顺序反过来就是他们的执行顺序。 在给定作用域中执行最后一条 defer 语句首先意味着最后一条 defer 语句可以关联将被其他 defer 语句清除的资源。

func f() {
    defer { print("First") }
    defer { print("Second") }
    defer { print("Third") }
}
f()
// 打印 "Third"
// 打印 "Second"
// 打印 "First"

defer 中语句,程序控制不能转移出当前 defer 语句作用域。

defer 语句语法

defer 语句  → defer 代码段


Do 语句

do 语句被用来开辟一个新作用域并可以可选地包含一个或多个包含了匹配被定义错误条件模式的 catch 分句。 声明在 do 语句作用域中的变量和常量只能在该作用域中被访问。

 Swift 中的 do 语句大括号( {} )和 C 中的一样用来限定一段代码段, 在运行时性能上不会造成损失。

 do 语句格式如下:

do {
    try expression
    statements
} catch pattern 1 {
    statements
} catch pattern 2 where condition {
    statements
}

像 switch 语句一样, 编译器尝试推断 catch 分句是否详尽具体。推断完成, 处理错误。 否则错误将被传出该作用域,这意味着错误必须被 catch 分句或包含 throws 的函数处理。

请用一个匹配所有错误模式的 catch 分句来处理错误, 例如通配符 ( _ )。 如果 catch 分句没有具体指定模式, 这个 catch 分句会将所有错误匹配和绑定到一个名为 error 的常量中。更多有关 catch 分句中模式使用的例子, 见 模式

一个如何在 do 语句中使用多个 catch 分句的例子, 见 错误处理

do 语句语法

do 语句  → do代码段 catch 分句 可选

catch 分句  → catch 分句 catch 分句 可选

catch 分句  → catch模式 可选 where 分句 可选 代码段


编译器控制语句

编译器控制语句让程序可以改变编译器方面的行为。 Swift 有三种编译器控制语句: 条件汇编块、单行控制语句和编译时间诊断语句。

编译器控制语句语法

编译器控制语句  → 条件编译块

编译器控制语句  → 单行控制语句

编译器控制语句  → 诊断语句

条件编译块

条件编译块让代码根据一个或多个编译条件编译。

每个条件编译块从 #if 编译指令开始到 #endif 编译指令结束。 一个简单条件编译块如下所示:

#if compilation condition
statements
#endif

不像 if 条件语句, 条件编译 在编译时执行。仅在编译时,编译条件 为真 true 时,语句 才会被编译和执行。

编译条件 可以包含字面量 true 和 false 布尔值, -D 可以作为命令行的标识符, 或下表中的一些平台条件。

平台条件 有效值
os() macOSiOSwatchOStvOSLinux
arch() i386x86_64armarm64
swift() >= 跟一个版本号数字
canImport() 一个模块名
targetEnvironment() simulator

swift() 平台条件的版本号由主要版本号、可选辅助版本号和可选补丁版本号等等组成, 用点 (.) 来分割每个部分的版本号。 不能在版本号和 >= 之间有空格。

平台条件函数 canImport() 的参数是一个不能代表所有平台的模块名。 这个条件函数测试该模块是否能导入,但不会真正导入模块。 如果该模块可以被导入,该函数返回 true;否则返回 false

当代码在模拟器被编译时,这个平台条件函数 targetEnvironment() 返回 true ;否则返回 false

注意

对于 ARM 64 架构设备,平台条件函数 arch(arm) 不会返回 true 。 当代码在 32 位 iOS 模拟器被编译时,平台条件函数 arch(i386) 返回 true

你可以用逻辑运算符 && 、 || 或  !  来组合多个编译条件,用一对圆括号合并它们。 这些操作符和逻辑运算符有相同的结合性和优先级, 可以和普通的布尔表达式联合使用。

和 if 语句一样,你能添加多种条件分支来测试不同的编译条件,通过添加几个 #elseif 分句。你也能用 #else 分句为最后一种添加条件分支。条件编译块可以包含如下几种分支:

#if compilation condition 1
statements to compile if compilation condition 1 is true
#elseif compilation condition 2
statements to compile if compilation condition 2 is true
#else
statements to compile if both compilation conditions are false
#endif

注意

在条件编译块中每个语句即使没有被编译也会被解析。 但也有一种例外,如果编译条件包含 swift() 平台条件:仅当 Swift 编译版本在平台条件下匹配特定版本时,语句才会被解析。 这个例外保证老编译器不会在新 Swift 版本中去解析语法。

条件编译语法

条件编译块  → if 指令分句 elseif 指令分句 可选 else 指令分句 可选 endif 指令

if 指令分句 → if 指令 编译条件 语句 可选

elseif 指令分句  → elseif 指令分句 elseif 指令分句 可选

elseif 指令分句  → elseif 指令 编译条件 语句 可选

else 指令分句  → else 指令 语句 可选

if 指令  → #if

elseif 指令  → #elseif

else 指令  → #else

endif 指令  → #endif

编译条件  → 平台条件

编译条件  → 标识符

编译条件  → 布尔字面量

编译条件  → ( 编译条件 )

编译条件  → ! 编译条件

编译条件  → 编译条件 && 编译条件

编译条件  → 编译条件 || 编译条件

平台条件 → os ( 操作系统 )

平台条件 → arch ( 架构 )

平台条件 → swift ( >= swift 版本 )

平台条件 → canImport ( 模块名 )

平台条件 → targetEnvironment ( 环境 )

操作系统  → macOS | iOS | watchOS | tvOS

架构  → i386 |x86_64 | arm | arm64

swift 版本  → 十进制数 swift 版本延续 可选

swift 版本延续  → . 十进制数 swift 版本延续可选

模块名  → 标识符

环境  → 模拟器

行控制语句

行控制语句可以用来指代和被编译源码行号和文件名不同的行号和文件名。 通过使用 Swift 的行控制语句来改变源代码执行位置来达到诊断和调试的目的。

一条行控制语句格式如下:

#sourceLocation(file: filename, line: line number)
#sourceLocation()

行控制语句开始,第一条行控制语句改变字面量表达式 #line 和 #file 的值。  行号 修改 #line 的值为一个任意大于 0 的值。文件名 修改 #file 的值为一个字面量字符串。

第二条行控制语句 #sourceLocation() 重置源代码的位置返回到默认行和文件名。

行控制语句语法

行控制语句  → #sourceLocation ( file: 文件名 , line: 行号 )

行控制语句  → #sourceLocation ( )

行号  → 一个十进制大于 0 的整数

文件名  → 静态字面量字符串

编译诊断语句

在编译期间,编译诊断语句会让编译器触发一个错误或一个警告。编译诊断语句格式如下:

#error("error message")
#warning("warning message")

第一条触发一个致命的 错误信息 并终止编译进程。第二条触发一条非致命的 警告信息 并让编译器继续运行。诊断信息必须为一条字面量字符串。 字面量字符串不能使用字符串的插补或拼接特性,但它们可以是多行。

编译诊断语句语法

诊断状态  → #error ( 诊断信息 )

诊断状态  → #warning ( 诊断信息 )

诊断消息  → 字面量字符串


有效性条件

有效性条件 像 if、 while 和 guard 语句一样根据特定平台参数的条件来在运行时检查 API 的有效性。

一条有效性条件格式如下:

if #available(platform name version, ..., *) {
    statements to execute if the APIs are available
} else {
    fallback statements to execute if the APIs are unavailable
}

你可以用有效性条件来执行一段代码,取决于你想使用的 API 在运行时是否可用。当编译器验证有效性条件代码块中 API 是可用时,它从有效性条件中使用信息。

有效性条件使用逗号 , 分隔平台名和版本号。 平台名使用 iOSmacOSwatchOS 、和 tvOS ,并带上一个相应的版本号做为版本。 * 参数是必须的,它指代任意其他平台,代码块在你指定的最小部署目标上被有效性条件守卫执行。

不像布尔条件,你不能用逻辑运算符 && 和 || 来连接有效性条件。

有效性条件语法

有效性条件  → #available ( 有效参数 )

有效性参数  → 有效性参数 | 有效性参数 , 有效性参数

有效性参数  → 平台名 平台版本

有效性参数  → *

平台名  → iOSiOSApplicationExtension

平台名  → macOS | macOSApplicationExtension

平台名  → watchOS

平台名  → tvOS

平台版本  → 十进制数

平台版本  → 十进制数 . 十进制数

平台版本  → 十进制数 . 十进制数 . 十进制数

本文章首发在 LearnKu.com 网站上。
上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~