這里的教程為Swift官方教程中文版。

語(yǔ)句(Statements)

在 Swift 中,有三種類(lèi)型的語(yǔ)句:簡(jiǎn)單語(yǔ)句、編譯器控制語(yǔ)句和控制流語(yǔ)句。簡(jiǎn)單語(yǔ)句是最常見(jiàn)的,用于構(gòu)造表達(dá)式或者聲明。編譯器控制語(yǔ)句允許程序改變編譯器的行為,包含編譯配置語(yǔ)句和行控制語(yǔ)句。

控制流語(yǔ)句則用于控制程序執(zhí)行的流程,Swift 中有多種類(lèi)型的控制流語(yǔ)句:循環(huán)語(yǔ)句、分支語(yǔ)句和控制轉(zhuǎn)移語(yǔ)句。循環(huán)語(yǔ)句用于重復(fù)執(zhí)行代碼塊;分支語(yǔ)句用于執(zhí)行滿足特定條件的代碼塊;控制轉(zhuǎn)移語(yǔ)句則用于改變代碼的執(zhí)行順序。另外,Swift 提供了 do 語(yǔ)句,用于構(gòu)建局部作用域,還用于錯(cuò)誤的捕獲和處理;還提供了 defer 語(yǔ)句,用于退出當(dāng)前作用域之前執(zhí)行清理操作。

是否將分號(hào)(;)添加到語(yǔ)句的末尾是可選的。但若要在同一行內(nèi)寫(xiě)多條獨(dú)立語(yǔ)句,則必須使用分號(hào)。

語(yǔ)句語(yǔ)法

語(yǔ)句表達(dá)式 ;可選

語(yǔ)句聲明 ;可選

語(yǔ)句循環(huán)語(yǔ)句 ;可選

語(yǔ)句分支語(yǔ)句 ;可選

語(yǔ)句帶標(biāo)簽的語(yǔ)句 ;可選

語(yǔ)句控制轉(zhuǎn)移語(yǔ)句 ;可選

語(yǔ)句defer 語(yǔ)句 ;可選

語(yǔ)句do 語(yǔ)句 :可選

語(yǔ)句編譯器控制語(yǔ)句

多條語(yǔ)句語(yǔ)句 多條語(yǔ)句可選

循環(huán)語(yǔ)句

循環(huán)語(yǔ)句會(huì)根據(jù)特定的循環(huán)條件來(lái)重復(fù)執(zhí)行代碼塊。Swift 提供三種類(lèi)型的循環(huán)語(yǔ)句:for-in 語(yǔ)句、while 語(yǔ)句和 repeat-while 語(yǔ)句。

通過(guò) break 語(yǔ)句和 continue 語(yǔ)句可以改變循環(huán)語(yǔ)句的控制流。有關(guān)這兩條語(yǔ)句,詳情參閱 Break 語(yǔ)句Continue 語(yǔ)句。

循環(huán)語(yǔ)句語(yǔ)法

loop-statement

循環(huán)語(yǔ)句for-in 語(yǔ)句

循環(huán)語(yǔ)句while 語(yǔ)句

循環(huán)語(yǔ)句repeat-while 語(yǔ)句

For-In 語(yǔ)句

for-in 語(yǔ)句會(huì)為集合(或?qū)崿F(xiàn)了 Sequence 協(xié)議的任意類(lèi)型)中的每一項(xiàng)執(zhí)行一次代碼塊。

for-in 語(yǔ)句的形式如下:

for item in collection {
    statements
}

for-in 語(yǔ)句在循環(huán)開(kāi)始前會(huì)調(diào)用集合表達(dá)式(collection expression)的 makeIterator() 方法來(lái)獲取一個(gè)實(shí)現(xiàn)了 IteratorProtocol 協(xié)議的迭代器類(lèi)型。接下來(lái)循環(huán)開(kāi)始,反復(fù)調(diào)用該迭代器的 next() 方法。如果其返回值不是 nil,它將會(huì)被賦給 item,然后執(zhí)行循環(huán)體語(yǔ)句,執(zhí)行完畢后回到循環(huán)開(kāi)始處,繼續(xù)重復(fù)這一過(guò)程;否則,既不會(huì)賦值也不會(huì)執(zhí)行循環(huán)體語(yǔ)句,for-in 語(yǔ)句至此執(zhí)行完畢。

for-in 語(yǔ)句語(yǔ)法

for-in-statement

for-in 語(yǔ)句for case可選 模式 in 表達(dá)式 where 子句可選 代碼塊

While 語(yǔ)句

只要循環(huán)條件為真,while 語(yǔ)句就會(huì)重復(fù)執(zhí)行代碼塊。

while 語(yǔ)句的形式如下:

while condition {
    statements
}

while 語(yǔ)句的執(zhí)行流程如下:

  1. 判斷條件(condition)的值。如果為 true,轉(zhuǎn)到第 2 步;如果為 falsewhile 語(yǔ)句至此執(zhí)行完畢。
  2. 執(zhí)行循環(huán)體中的語(yǔ)句,然后重復(fù)第 1 步。

由于會(huì)在執(zhí)行循環(huán)體中的語(yǔ)句前判斷條件的值,因此循環(huán)體中的語(yǔ)句可能會(huì)被執(zhí)行若干次,也可能一次也不會(huì)被執(zhí)行。

條件的結(jié)果必須是 Bool 類(lèi)型或者 Bool 的橋接類(lèi)型。另外,條件語(yǔ)句也可以使用可選綁定,請(qǐng)參閱 可選綁定。

while 語(yǔ)句語(yǔ)法

while-statement

while 語(yǔ)句while 條件子句 代碼塊

condition-clause

條件子句表達(dá)式 | 表達(dá)式 , 條件列表

condition

條件表達(dá)式 |可用性條件 | case 條件 | 可選綁定條件

case-condition

case 條件case 模式 構(gòu)造器

optional-binding-condition

可選綁定條件let 模式 構(gòu)造器 | var 模式 構(gòu)造器

Repeat-While 語(yǔ)句

repeat-while 語(yǔ)句至少執(zhí)行一次代碼塊,之后只要循環(huán)條件為真,就會(huì)重復(fù)執(zhí)行代碼塊。

repeat-while 語(yǔ)句的形式如下:

repeat {
    statements
} while condition

repeat-while 語(yǔ)句的執(zhí)行流程如下:

  1. 執(zhí)行循環(huán)體中的語(yǔ)句,然后轉(zhuǎn)到第 2 步。
  2. 判斷條件的值。如果為 true,重復(fù)第 1 步;如果為 false,repeat-while 語(yǔ)句至此執(zhí)行完畢。

由于條件的值是在循環(huán)體中的語(yǔ)句執(zhí)行后才進(jìn)行判斷,因此循環(huán)體中的語(yǔ)句至少會(huì)被執(zhí)行一次。

條件的結(jié)果必須是 Bool 類(lèi)型或者 Bool 的橋接類(lèi)型。另外,條件語(yǔ)句也可以使用可選綁定,請(qǐng)參閱 可選綁定。

repeat-while 語(yǔ)句語(yǔ)法

repeat-while-statement

repeat-while 語(yǔ)句repeat 代碼塊 while 表達(dá)式

分支語(yǔ)句

分支語(yǔ)句會(huì)根據(jù)一個(gè)或者多個(gè)條件來(lái)執(zhí)行指定部分的代碼。分支語(yǔ)句中的條件將會(huì)決定程序如何分支以及執(zhí)行哪部分代碼。Swift 提供三種類(lèi)型的分支語(yǔ)句:if 語(yǔ)句、 guard 語(yǔ)句和 switch 語(yǔ)句。

if 語(yǔ)句和 switch 語(yǔ)句中的控制流可以用 break 語(yǔ)句改變,請(qǐng)參閱 Break 語(yǔ)句。

分支語(yǔ)句語(yǔ)法

branch-statement

分支語(yǔ)句if 語(yǔ)句

分支語(yǔ)句guard 語(yǔ)句

分支語(yǔ)句switch 語(yǔ)句

If 語(yǔ)句

if 語(yǔ)句會(huì)根據(jù)一個(gè)或多個(gè)條件來(lái)決定執(zhí)行哪一塊代碼。

if 語(yǔ)句有兩種基本形式,無(wú)論哪種形式,都必須有花括號(hào)。

第一種形式是當(dāng)且僅當(dāng)條件為真時(shí)執(zhí)行代碼,像下面這樣:

if condition {
    statements
}

第二種形式是在第一種形式的基礎(chǔ)上添加 else 語(yǔ)句(通過(guò)引入 else 關(guān)鍵字),并且用于:當(dāng)條件為真時(shí)執(zhí)行一部分代碼,當(dāng)這同一個(gè)條件為假的時(shí)候執(zhí)行另一部分代碼。當(dāng)只有一個(gè) else 語(yǔ)句時(shí),if 語(yǔ)句具有以下的形式:

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

if 語(yǔ)句的 else 語(yǔ)句也可包含另一個(gè) if 語(yǔ)句,從而形成一條鏈來(lái)測(cè)試更多的條件,像下面這樣:

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 語(yǔ)句中條件的結(jié)果必須是 Bool 類(lèi)型或者 Bool 的橋接類(lèi)型。另外,條件語(yǔ)句也可以使用可選綁定,請(qǐng)參閱 可選綁定。

if 語(yǔ)句語(yǔ)法

if-statement

if 語(yǔ)句if 條件子句 代碼塊 else 子句可選

else-clause

else 子句else 代碼塊 | else if 語(yǔ)句

Guard 語(yǔ)句

如果一個(gè)或者多個(gè)條件不成立,可用 guard 語(yǔ)句來(lái)退出當(dāng)前作用域。

guard 語(yǔ)句的格式如下:

guard condition else {
    statements
}

guard 語(yǔ)句中條件的結(jié)果必須是 Bool 類(lèi)型或者 Bool 的橋接類(lèi)型。另外,條件也可以是一條可選綁定,請(qǐng)參閱 可選綁定

guard 語(yǔ)句中進(jìn)行可選綁定的任何常量或者變量,其可用范圍從聲明開(kāi)始直到作用域結(jié)束。

guard 語(yǔ)句必須有 else 子句,而且必須在該子句中調(diào)用返回類(lèi)型是 Never 的函數(shù),或者使用下面的語(yǔ)句退出當(dāng)前作用域:

  • return
  • break
  • continue
  • throw

關(guān)于控制轉(zhuǎn)移語(yǔ)句,請(qǐng)參閱 控制轉(zhuǎn)移語(yǔ)句。關(guān)于 Never 返回類(lèi)型的函數(shù),請(qǐng)參閱 永不返回的函數(shù)。

guard 語(yǔ)句語(yǔ)法

guard-statement

guard 語(yǔ)句guard 條件子句 else 代碼塊

Switch 語(yǔ)句

switch 語(yǔ)句會(huì)根據(jù)控制表達(dá)式的值來(lái)決定執(zhí)行哪部分代碼。

switch 語(yǔ)句的形式如下:

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 語(yǔ)句會(huì)先計(jì)算控制表達(dá)式的值,然后與每一個(gè) case 的模式進(jìn)行匹配。如果匹配成功,程序?qū)?huì)執(zhí)行對(duì)應(yīng)的 case 中的語(yǔ)句。另外,每一個(gè) case 的作用域都不能為空,也就是說(shuō)在每一個(gè) case 的冒號(hào)(:)后面必須至少有一條語(yǔ)句。如果你不想在匹配到的 case 中執(zhí)行代碼,只需在該 case 中寫(xiě)一條 break 語(yǔ)句即可。

可以用作控制表達(dá)式的值是十分靈活的。除了標(biāo)量類(lèi)型外,如 Int、Character,你可以使用任何類(lèi)型的值,包括浮點(diǎn)數(shù)、字符串、元組、自定義類(lèi)型的實(shí)例和可選類(lèi)型??刂票磉_(dá)式的值還可以用來(lái)匹配枚舉類(lèi)型中的成員值或是檢查該值是否包含在指定的 Range 中。關(guān)于如何在 switch 語(yǔ)句中使用這些類(lèi)型,請(qǐng)參閱 控制流 一章中的 Switch。

每個(gè) case 的模式后面可以有一個(gè) where 子句。where 子句由 where 關(guān)鍵字緊跟一個(gè)提供額外條件的表達(dá)式組成。因此,當(dāng)且僅當(dāng)控制表達(dá)式匹配一個(gè) case 的模式且 where 子句的表達(dá)式為真時(shí),case 中的語(yǔ)句才會(huì)被執(zhí)行。在下面的例子中,控制表達(dá)式只會(huì)匹配包含兩個(gè)相等元素的元組,例如 (1, 1)

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

正如上面這個(gè)例子,也可以在模式中使用 let(或 var)語(yǔ)句來(lái)綁定常量(或變量)。這些常量(或變量)可以在對(duì)應(yīng)的 where 子句以及 case 中的代碼中使用。但是,如果一個(gè) case 中含有多個(gè)模式,所有的模式必須包含相同的常量(或變量)綁定,并且每一個(gè)綁定的常量(或變量)必須在所有的條件模式中都有相同的類(lèi)型。

switch 語(yǔ)句也可以包含默認(rèn)分支,使用 default 關(guān)鍵字表示。只有所有 case 都無(wú)法匹配控制表達(dá)式時(shí),默認(rèn)分支中的代碼才會(huì)被執(zhí)行。一個(gè) switch 語(yǔ)句只能有一個(gè)默認(rèn)分支,而且必須在 switch 語(yǔ)句的最后面。

switch 語(yǔ)句中 case 的匹配順序和源代碼中的書(shū)寫(xiě)順序保持一致。因此,當(dāng)多個(gè)模式都能匹配控制表達(dá)式時(shí),只有第一個(gè)匹配的 case 中的代碼會(huì)被執(zhí)行。

Switch 語(yǔ)句必須是詳盡的

在 Swift 中,switch 語(yǔ)句中控制表達(dá)式的每一個(gè)可能的值都必須至少有一個(gè) case 與之對(duì)應(yīng)。在某些無(wú)法面面俱到的情況下(例如,表達(dá)式的類(lèi)型是 Int),你可以使用 default 分支滿足該要求。

對(duì)未來(lái)枚舉的 case 進(jìn)行 switch

非凍結(jié)枚舉(nonfronzen enumeration)是一種特殊的枚舉類(lèi)型,它可能在未來(lái)會(huì)增加新的枚舉 case,即使這時(shí)候你已經(jīng)編譯并且發(fā)布了你的應(yīng)用,所以在 switch 非凍結(jié)枚舉前需要深思熟慮。當(dāng)一個(gè)庫(kù)的作者們把一個(gè)枚舉標(biāo)記為非凍結(jié)的,這意味著他們保留了增加新的枚舉 case 的權(quán)利,并且任何和這個(gè)枚舉交互的代碼都必須在無(wú)需重新編譯的條件下能夠處理那些未來(lái)可能新加入的 case 。只有演進(jìn)模式的庫(kù)代碼、標(biāo)準(zhǔn)庫(kù)代碼、用 Swift 實(shí)現(xiàn)的 Apple 框架、C 以及 Objective-C 代碼才能夠聲明非凍結(jié)枚舉。更多關(guān)于凍結(jié)和非凍結(jié)枚舉的內(nèi)容,請(qǐng)參閱 凍結(jié)。

當(dāng)你對(duì)未來(lái)枚舉進(jìn)行 switch 時(shí),你總是需要有一個(gè) default case,即使每種枚舉類(lèi)型都已經(jīng)有對(duì)應(yīng)的 case 了。你可以在 default 前標(biāo)注 @unknown,意思是這個(gè) case 應(yīng)該只匹配未來(lái)加入的枚舉 case。如果你的 default case 中匹配了任何在編譯時(shí)就能確定的枚舉 case,Swift 會(huì)拋出一個(gè)警告。這可以很好地提醒你庫(kù)的作者已經(jīng)新增了一種 case,并且你還沒(méi)有去處理。

以下就是一個(gè)例子,我們對(duì)標(biāo)準(zhǔn)庫(kù)的 Mirror.AncestorRepresentation 枚舉進(jìn)行 switch 操作。每當(dāng)有新的 case 加入,我們會(huì)得到一個(gè)警告,提示我們要去處理它。

let representation: Mirror.AncestorRepresentation = .generated
switch representation {
case .customized:
    print("Use the nearest ancestor’s implementation.")
case .generated:
    print("Generate a default mirror for all ancestor classes.")
case .suppressed:
    print("Suppress the representation of all ancestor classes.")
@unknown default:
    print("Use a representation that was unknown when this code was compiled.")
}
// Prints "Generate a default mirror for all ancestor classes."

不存在隱式落入

當(dāng)匹配到的 case 中的代碼執(zhí)行完畢后,switch 語(yǔ)句會(huì)直接退出,而不會(huì)繼續(xù)執(zhí)行下一個(gè) case 。這就意味著,如果你想執(zhí)行下一個(gè) case,需要顯式地在當(dāng)前 case 中使用 fallthrough 語(yǔ)句。關(guān)于 fallthrough 語(yǔ)句的更多信息,請(qǐng)參閱 Fallthrough 語(yǔ)句。

switch 語(yǔ)句語(yǔ)法

switch-statement

switch 語(yǔ)句switch 表達(dá)式 { switch-case 列表可選 }

switch-cases

switch case 列表switch-case switch-case 列表可選

switch-case

switch casecase 標(biāo)簽 多條語(yǔ)句 | default 標(biāo)簽 多條語(yǔ)句 | conditional-switch-case

case-label

case 標(biāo)簽屬性可選 case case 項(xiàng)列表 :

case-item-list

case 項(xiàng)列表模式 where 子句可選 | 模式 where 子句可選 , case 項(xiàng)列表

default-label

default 標(biāo)簽屬性可選 default :

where-clause

where-clausewhere where 表達(dá)式

where-expression

where-expression表達(dá)式

grammar-conditional-switch-case

conditional-switch-caseswitch-if-directive-clause switch-elseif-directive-clauses 可選 switch-else-directive-clause 可選 endif-directive

grammar-switch-if-directive-clause

switch-if-directive 語(yǔ)句if-directive compilation-condition switch-cases 可選

grammar-switch-elseif-directive-clauses

switch-elseif-directive 語(yǔ)句(復(fù)數(shù))elseif-directive-clause switch-elseif-directive-clauses可選

grammar-switch-elseif-directive-clause

switch-elseif-directive 語(yǔ)句elseif-directive compilation-condition switch-cases可選

grammar-switch-else-directive-clause

switch-else-directive 語(yǔ)句else-directive switch-cases 可選

帶標(biāo)簽的語(yǔ)句

你可以在循環(huán)語(yǔ)句或 switch 語(yǔ)句前面加上標(biāo)簽,它由標(biāo)簽名和緊隨其后的冒號(hào)(:)組成。在 breakcontinue 后面跟上標(biāo)簽名可以顯式地在循環(huán)語(yǔ)句或 switch 語(yǔ)句中改變相應(yīng)的控制流。關(guān)于這兩條語(yǔ)句用法,請(qǐng)參閱 Break 語(yǔ)句Continue 語(yǔ)句。

標(biāo)簽的作用域在該標(biāo)簽所標(biāo)記的語(yǔ)句內(nèi)。可以嵌套使用帶標(biāo)簽的語(yǔ)句,但標(biāo)簽名必須唯一。

關(guān)于使用帶標(biāo)簽的語(yǔ)句的例子,請(qǐng)參閱 控制流 一章中的 帶標(biāo)簽的語(yǔ)句。

帶標(biāo)簽的語(yǔ)句語(yǔ)法

labeled-statement

帶標(biāo)簽的語(yǔ)句語(yǔ)句標(biāo)簽 循環(huán)語(yǔ)句

帶標(biāo)簽的語(yǔ)句語(yǔ)句標(biāo)簽 if 語(yǔ)句

帶標(biāo)簽的語(yǔ)句語(yǔ)句標(biāo)簽 switch 語(yǔ)句

帶標(biāo)簽的語(yǔ)句語(yǔ)句標(biāo)簽 do 語(yǔ)句

statement-label

語(yǔ)句標(biāo)簽標(biāo)簽名稱(chēng) :

label-name

標(biāo)簽名稱(chēng)標(biāo)識(shí)符

控制轉(zhuǎn)移語(yǔ)句

控制轉(zhuǎn)移語(yǔ)句能夠無(wú)條件地把控制權(quán)從一片代碼轉(zhuǎn)移到另一片代碼,從而改變代碼執(zhí)行的順序。Swift 提供五種類(lèi)型的控制轉(zhuǎn)移語(yǔ)句:break 語(yǔ)句、continue 語(yǔ)句、fallthrough 語(yǔ)句、return 語(yǔ)句和 throw 語(yǔ)句。

控制轉(zhuǎn)移語(yǔ)句語(yǔ)法

control-transfer-statement

控制轉(zhuǎn)移語(yǔ)句break 語(yǔ)句

控制轉(zhuǎn)移語(yǔ)句continue 語(yǔ)句

控制轉(zhuǎn)移語(yǔ)句fallthrough 語(yǔ)句

控制轉(zhuǎn)移語(yǔ)句return 語(yǔ)句

控制轉(zhuǎn)移語(yǔ)句throw 語(yǔ)句

Break 語(yǔ)句

break 語(yǔ)句用于終止循環(huán)語(yǔ)句、if 語(yǔ)句或 switch 語(yǔ)句的執(zhí)行。使用 break 語(yǔ)句時(shí),可以只寫(xiě) break 這個(gè)關(guān)鍵詞,也可以在 break 后面跟上標(biāo)簽名,像下面這樣:

break

break label name

當(dāng) break 語(yǔ)句后面帶標(biāo)簽名時(shí),可用于終止由這個(gè)標(biāo)簽標(biāo)記的循環(huán)語(yǔ)句、if 語(yǔ)句或 switch 語(yǔ)句的執(zhí)行。

而只寫(xiě) break 時(shí),則會(huì)終止 switch 語(yǔ)句或 break 語(yǔ)句所屬的最內(nèi)層循環(huán)語(yǔ)句的執(zhí)行。不能使用 break 語(yǔ)句來(lái)終止未使用標(biāo)簽的 if 語(yǔ)句。

無(wú)論哪種情況,控制權(quán)都會(huì)被轉(zhuǎn)移給被終止的控制流語(yǔ)句后面的第一行語(yǔ)句。

關(guān)于使用 break 語(yǔ)句的例子,請(qǐng)參閱 控制流 一章的 Break帶標(biāo)簽的語(yǔ)句。

break 語(yǔ)句語(yǔ)法

break-statement

break 語(yǔ)句break 標(biāo)簽名稱(chēng)可選

Continue 語(yǔ)句

continue 語(yǔ)句用于終止循環(huán)中當(dāng)前迭代的執(zhí)行,但不會(huì)終止該循環(huán)的執(zhí)行。使用 continue 語(yǔ)句時(shí),可以只寫(xiě) continue 這個(gè)關(guān)鍵詞,也可以在 continue 后面跟上標(biāo)簽名,像下面這樣:

continue

continue label name

當(dāng) continue 語(yǔ)句后面帶標(biāo)簽名時(shí),可用于終止由這個(gè)標(biāo)簽標(biāo)記的循環(huán)中當(dāng)前迭代的執(zhí)行。

而當(dāng)只寫(xiě) continue 時(shí),可用于終止 continue 語(yǔ)句所屬的最內(nèi)層循環(huán)中當(dāng)前迭代的執(zhí)行。

在這兩種情況下,控制權(quán)都會(huì)被轉(zhuǎn)移給循環(huán)語(yǔ)句的條件語(yǔ)句。

for 語(yǔ)句中,continue 語(yǔ)句執(zhí)行后,增量表達(dá)式還是會(huì)被計(jì)算,這是因?yàn)槊看窝h(huán)體執(zhí)行完畢后,增量表達(dá)式都會(huì)被計(jì)算。

關(guān)于使用 continue 語(yǔ)句的例子,請(qǐng)參閱 控制流 一章的 Continue帶標(biāo)簽的語(yǔ)句。

continue 語(yǔ)句語(yǔ)法

continue-statement

continue 語(yǔ)句continue 標(biāo)簽名稱(chēng)可選

Fallthrough 語(yǔ)句

fallthrough 語(yǔ)句用于在 switch 語(yǔ)句中轉(zhuǎn)移控制權(quán)。fallthrough 語(yǔ)句會(huì)把控制權(quán)從 switch 語(yǔ)句中的一個(gè) case 轉(zhuǎn)移到下一個(gè) case。這種控制權(quán)轉(zhuǎn)移是無(wú)條件的,即使下一個(gè) case 的模式與 switch 語(yǔ)句的控制表達(dá)式的值不匹配。

fallthrough 語(yǔ)句可出現(xiàn)在 switch 語(yǔ)句中的任意 case 中,但不能出現(xiàn)在最后一個(gè) case 中。同時(shí),fallthrough 語(yǔ)句也不能把控制權(quán)轉(zhuǎn)移到使用了值綁定的 case。

關(guān)于在 switch 語(yǔ)句中使用 fallthrough 語(yǔ)句的例子,請(qǐng)參閱 控制流 一章的 控制轉(zhuǎn)移語(yǔ)句。

fallthrough 語(yǔ)句語(yǔ)法

fallthrough-statement

fallthrough 語(yǔ)句fallthrough

Return 語(yǔ)句

return 語(yǔ)句用于在函數(shù)或方法的實(shí)現(xiàn)中將控制權(quán)轉(zhuǎn)移到調(diào)用函數(shù)或方法,接著程序?qū)?huì)從調(diào)用位置繼續(xù)向下執(zhí)行。

使用 return 語(yǔ)句時(shí),可以只寫(xiě) return 這個(gè)關(guān)鍵詞,也可以在 return 后面跟上表達(dá)式,像下面這樣:

return

return expression

當(dāng) return 語(yǔ)句后面帶表達(dá)式時(shí),表達(dá)式的值將會(huì)返回給調(diào)用函數(shù)或方法。如果表達(dá)式的值的類(lèi)型與函數(shù)或者方法聲明的返回類(lèi)型不匹配,Swift 則會(huì)在返回表達(dá)式的值之前將表達(dá)式的值的類(lèi)型轉(zhuǎn)換為返回類(lèi)型。

注意

正如 可失敗構(gòu)造器 中所描述的,return nil 在可失敗構(gòu)造器中用于表明構(gòu)造失敗。

而只寫(xiě) return 時(shí),僅僅是從該函數(shù)或方法中返回,而不返回任何值(也就是說(shuō),函數(shù)或方法的返回類(lèi)型為 Void 或者說(shuō) ())。

return 語(yǔ)句語(yǔ)法

return-statement

return 語(yǔ)句return 表達(dá)式可選

Throw 語(yǔ)句

throw 語(yǔ)句出現(xiàn)在拋出函數(shù)或者拋出方法體內(nèi),或者類(lèi)型被 throws 關(guān)鍵字標(biāo)記的閉包表達(dá)式體內(nèi)。

throw 語(yǔ)句使程序在當(dāng)前作用域結(jié)束執(zhí)行,并向外圍作用域傳播錯(cuò)誤。拋出的錯(cuò)誤會(huì)一直傳遞,直到被 do 語(yǔ)句的 catch 子句處理掉。

throw 語(yǔ)句由 throw 關(guān)鍵字緊跟一個(gè)表達(dá)式組成,如下所示:

throw expression

表達(dá)式的結(jié)果必須符合 ErrorType 協(xié)議。

關(guān)于如何使用 throw 語(yǔ)句的例子,請(qǐng)參閱 錯(cuò)誤處理 一章的 用 throwing 函數(shù)傳遞錯(cuò)誤。

throw 語(yǔ)句語(yǔ)法

throw-statement

throw 語(yǔ)句throw 表達(dá)式

Defer 語(yǔ)句

defer 語(yǔ)句用于在退出當(dāng)前作用域之前執(zhí)行代碼。

defer 語(yǔ)句形式如下:

defer {
    statements
}

defer 語(yǔ)句中的語(yǔ)句無(wú)論程序控制如何轉(zhuǎn)移都會(huì)被執(zhí)行。在某些情況下,例如,手動(dòng)管理資源時(shí),比如關(guān)閉文件描述符,或者即使拋出了錯(cuò)誤也需要執(zhí)行一些操作時(shí),就可以使用 defer 語(yǔ)句。

如果多個(gè) defer 語(yǔ)句出現(xiàn)在同一作用域內(nèi),那么它們執(zhí)行的順序與出現(xiàn)的順序相反。給定作用域中的第一個(gè) defer 語(yǔ)句,會(huì)在最后執(zhí)行,這意味著代碼中最靠后的 defer 語(yǔ)句中引用的資源可以被其他 defer 語(yǔ)句清理掉。

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

defer 語(yǔ)句中的語(yǔ)句無(wú)法將控制權(quán)轉(zhuǎn)移到 defer 語(yǔ)句外部。

defer 語(yǔ)句語(yǔ)法

defer-statement

延遲語(yǔ)句defer 代碼塊

Do 語(yǔ)句

do 語(yǔ)句用于引入一個(gè)新的作用域,該作用域中可以含有一個(gè)或多個(gè) catch 子句,catch 子句中定義了一些匹配錯(cuò)誤條件的模式。do 語(yǔ)句作用域內(nèi)定義的常量和變量只能在 do 語(yǔ)句作用域內(nèi)使用。

Swift 中的 do 語(yǔ)句與 C 中限定代碼塊界限的大括號(hào)({})很相似,也并不會(huì)降低程序運(yùn)行時(shí)的性能。

do 語(yǔ)句的形式如下:

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

如同 switch 語(yǔ)句,編譯器會(huì)判斷 catch 子句是否有遺漏。如果 catch 子句沒(méi)有遺漏,則認(rèn)為錯(cuò)誤已被處理。否則,錯(cuò)誤會(huì)自動(dòng)傳遞到外圍作用域,被某個(gè) catch 子句處理掉或者被用 throws 關(guān)鍵字聲明的拋出函數(shù)繼續(xù)向外拋出。

為了確保錯(cuò)誤已經(jīng)被處理,可以讓 catch 子句使用匹配所有錯(cuò)誤的模式,如通配符模式(_)。如果一個(gè) catch 子句不指定一種具體模式,catch 子句會(huì)匹配任何錯(cuò)誤,并綁定到名為 error 的局部常量。有關(guān)在 catch 子句中使用模式的更多信息,請(qǐng)參閱 模式。

關(guān)于如何在 do 語(yǔ)句中使用一系列 catch 子句的例子,請(qǐng)參閱 錯(cuò)誤處理。

do 語(yǔ)句語(yǔ)法

do-statement

do 語(yǔ)句do 代碼塊 多條 catch 子句可選

catch-clauses

多條 catch 子句catch 子句 多條 catch 子句可選

catch-clause

catch 子句catch 模式可選 where 子句可選 代碼塊

編譯器控制語(yǔ)句

編譯器控制語(yǔ)句允許程序改變編譯器的行為。Swift 有三種編譯器控制語(yǔ)句:條件編譯語(yǔ)句、線路控制語(yǔ)句和編譯時(shí)診斷語(yǔ)句。

編譯器控制語(yǔ)句語(yǔ)法

compiler-control-statement

編譯器控制語(yǔ)句條件編譯語(yǔ)句

編譯器控制語(yǔ)句線路控制語(yǔ)句

編譯器控制語(yǔ)句診斷語(yǔ)句

條件編譯代碼塊

條件編譯代碼塊可以根據(jù)一個(gè)或多個(gè)配置來(lái)有條件地編譯代碼。

每一個(gè)條件編譯代碼塊都以 #if 開(kāi)始,#endif 結(jié)束。如下:

#if compilation condition
statements
#endif

if 語(yǔ)句的條件不同,編譯配置的條件是在編譯時(shí)進(jìn)行判斷的。只有編譯配置在編譯時(shí)判斷為 true 的情況下,相應(yīng)的語(yǔ)句才會(huì)被編譯和執(zhí)行。

編譯配置可以是 truefalse 的字面量,也可以是使用 -D 命令行標(biāo)志的標(biāo)識(shí)符,或者是下列表格中的任意一個(gè)平臺(tái)檢測(cè)函數(shù)。

函數(shù) 可用參數(shù)
os() OSX, iOS, watchOS, tvOS, Linux
arch() i386, x86_64, arm, arm64
swift() >=< 后跟版本號(hào)
compiler() >=< 后跟版本號(hào)
canImport() 模塊名
targetEnvironment() simulator,macCatalyst

swift()compiler() 之后的版本號(hào)包含有主版本號(hào),可選副版本號(hào),可選補(bǔ)丁版本號(hào)類(lèi)似,并且用(.)來(lái)分隔。在比較符和版本號(hào)之間不能有空格,版本號(hào)與前面的函數(shù)相對(duì)應(yīng),比如 compiler() 對(duì)應(yīng)的就是這個(gè)編譯器的版本號(hào),swift() 對(duì)應(yīng)的就是你要編譯的 Swift 語(yǔ)言的版本號(hào)。舉個(gè)簡(jiǎn)單的例子,如果你在使用 Swift 5 的編譯器,想編譯 Swift 4.2 ,可以看下面的例子:

#if compiler(>=5)
print("Compiled with the Swift 5 compiler or later")
#endif
#if swift(>=4.2)
print("Compiled in Swift 4.2 mode or later")
#endif
#if compiler(>=5) && swift(<5)
print("Compiled with the Swift 5 compiler or later in a Swift mode earlier than 5")
#endif
// 打印 "Compiled with the Swift 5 compiler or later"
// 打印 "Compiled in Swift 4.2 mode or later"
// 打印 "Compiled with the Swift 5 compiler or later in a Swift mode earlier than 5"

canImport() 后面跟的變量是模塊的名字,這里這個(gè)模塊可能并不是每個(gè)平臺(tái)上都存在的。使用它來(lái)檢測(cè)是否可以導(dǎo)入這個(gè)模塊,如果模塊存在就返回 true 否則返回 false

targetEnvironment() 當(dāng)為模擬器編譯時(shí)返回 true,否則返回 false

注意

arch(arm) 平臺(tái)檢測(cè)函數(shù)在 ARM 64 位設(shè)備上不會(huì)返回 true。如果代碼在 32 位的 iOS 模擬器上編譯,arch(i386) 平臺(tái)檢測(cè)函數(shù)會(huì)返回 true。

你可以使用邏輯操作符 &&、||! 來(lái)組合多個(gè)編譯配置,還可以使用圓括號(hào)來(lái)進(jìn)行分組。

就像 if 語(yǔ)句一樣,你可以使用 #elseif 子句來(lái)添加任意多個(gè)條件分支來(lái)測(cè)試不同的編譯配置。你也可以使用 #else 子句來(lái)添加最終的條件分支。包含多個(gè)分支的編譯配置語(yǔ)句例子如下:

#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

注意

即使沒(méi)有被編譯,編譯配置中的語(yǔ)句仍然會(huì)被解析。然而,唯一的例外是編譯配置語(yǔ)句中包含語(yǔ)言版本檢測(cè)函數(shù):僅當(dāng) Swift 編譯器版本和語(yǔ)言版本檢測(cè)函數(shù)中指定的版本號(hào)匹配時(shí),語(yǔ)句才會(huì)被解析。這種設(shè)定能確保舊的編譯器不會(huì)嘗試去解析新 Swift 版本的語(yǔ)法。

build-config-statement

條件編譯代碼塊語(yǔ)法

grammar-conditional-compilation-block

條件編譯代碼塊if-directive 語(yǔ)句 elseif-directive 語(yǔ)句(復(fù)數(shù))可選 else-directive 語(yǔ)句可選 endif-directive

grammar-if-directive-clause

if-directive 語(yǔ)句if-directive 編譯條件 語(yǔ)句(復(fù)數(shù))可選

grammar-elseif-directive-clauses

elseif-directive 語(yǔ)句(復(fù)數(shù))elseif-directive 語(yǔ)句 elseif-directive 語(yǔ)句(復(fù)數(shù))

grammar-elseif-directive-clauses

elseif-directive 語(yǔ)句elseif-directive 編譯條件 語(yǔ)句(復(fù)數(shù))可選

grammar-else-directive-clause

else-directive 語(yǔ)句else-directive 語(yǔ)句(復(fù)數(shù))可選

if-directive#if

elseif-directive#elseif

else-directive#else

endif-directive#endif

compilation-condition

編譯條件平臺(tái)條件

編譯條件標(biāo)識(shí)符

編譯條件布爾值字面量

編譯條件( 編譯條件 )

編譯條件! 編譯條件

編譯條件編譯條件 && 編譯條件

編譯條件編譯條件 || 編譯條件

grammar-platform-condition

grammar-platform-condition-os

平臺(tái)條件os ( 操作系統(tǒng) )

grammar-platform-condition-arch

平臺(tái)條件arch ( 架構(gòu) )

grammar-platform-condition-swift

平臺(tái)條件swift ( >= swift 版本 ) | swift ( < swift 版本 )

grammar-platform-condition-compiler

平臺(tái)條件compiler ( >= swift 版本 ) | compiler ( < swift 版本 )

grammar-platform-condition-canImport

平臺(tái)條件canImport ( 模塊名 )

grammar-platform-condition-targetEnvironment

平臺(tái)條件targetEnvironment ( 環(huán)境 )

operating-system

操作系統(tǒng)macOS | iOS | watchOS | tvOS

architecture

架構(gòu)i386 | x86_64 | arm | arm64

swift-version

swift 版本十進(jìn)制數(shù)字 -. -swift 版本延續(xù) 可選

grammar-swift-version-continuation

swift 版本延續(xù). 十進(jìn)制數(shù)字 swift 版本延續(xù) 可選

grammar-module-name

模塊名identifier

grammar-environment

環(huán)境模擬器

行控制語(yǔ)句

行控制語(yǔ)句可以為被編譯的源代碼指定行號(hào)和文件名,從而改變?cè)创a的定位信息,以便進(jìn)行分析和調(diào)試。

行控制語(yǔ)句形式如下:

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

#sourceLocation()

第一種的行控制語(yǔ)句會(huì)改變?cè)撜Z(yǔ)句之后的代碼中的字面量表達(dá)式 #line#file 所表示的值。行號(hào) 是一個(gè)大于 0 的整形字面量,會(huì)改變 #line 表達(dá)式的值。文件名 是一個(gè)字符串字面量,會(huì)改變 #file 表達(dá)式的值。

第二種的行控制語(yǔ)句,#sourceLocation(),會(huì)將源代碼的定位信息重置回默認(rèn)的行號(hào)和文件名。

line-control-statement

行控制語(yǔ)句語(yǔ)法

行控制語(yǔ)句#sourceLocation(file:文件名,line:行號(hào))

行控制語(yǔ)句#sourceLocation( )

line-number

行號(hào) → 大于 0 的十進(jìn)制整數(shù)

file-name

文件名靜態(tài)字符串字面量

編譯時(shí)診斷語(yǔ)句

編譯時(shí)診斷語(yǔ)句允許編譯器在編譯的時(shí)候可以發(fā)出錯(cuò)誤或者警告。語(yǔ)句形式如下:

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

第一句會(huì)拋出錯(cuò)誤信息并終止編譯,第二句會(huì)發(fā)出警告信息但是編譯會(huì)繼續(xù)進(jìn)行。你可以通過(guò)靜態(tài)字符串字面量來(lái)書(shū)寫(xiě)診斷信息,靜態(tài)字符串字面量不能使用字符串 interpolation 或者 concatenation,但可以使用多行的形式。

編譯時(shí)診斷語(yǔ)句語(yǔ)法

grammar-compile-time-diagnostic-statement

診斷語(yǔ)句#error ( 診斷消息 )

診斷語(yǔ)句#warning ( 診斷消息 )

診斷語(yǔ)句靜態(tài)字符串字面量

可用性條件

可用性條件可作為 if,whileguard 語(yǔ)句的條件,可以在運(yùn)行時(shí)基于特定的平臺(tái)參數(shù)來(lái)查詢 API 的可用性。

可用性條件的形式如下:

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

使用可用性條件來(lái)執(zhí)行一個(gè)代碼塊時(shí),取決于使用的 API 在運(yùn)行時(shí)是否可用,編譯器會(huì)根據(jù)可用性條件提供的信息來(lái)決定是否執(zhí)行相應(yīng)的代碼塊。

可用性條件使用一系列逗號(hào)分隔的平臺(tái)名稱(chēng)和版本。使用 iOS,OSX,以及 watchOS 等作為平臺(tái)名稱(chēng),并寫(xiě)上相應(yīng)的版本號(hào)。* 參數(shù)是必須寫(xiě)的,用于處理未來(lái)的潛在平臺(tái)??捎眯詶l件確保了運(yùn)行時(shí)的平臺(tái)不低于條件中指定的平臺(tái)版本時(shí)才執(zhí)行代碼塊。

與布爾類(lèi)型的條件不同,不能用邏輯運(yùn)算符 &&|| 組合可用性條件。

可用性條件語(yǔ)法

availability-condition

可用性條件#available ( 可用性參數(shù)列表 )

availability-arguments

可用性參數(shù)列表可用性參數(shù) | 可用性參數(shù) , 可用性參數(shù)列表

availability-argument

可用性參數(shù)平臺(tái)名稱(chēng) 平臺(tái)版本

可用性條件*

platform-name

平臺(tái)名稱(chēng)iOS | iOSApplicationExtension

平臺(tái)名稱(chēng)OSX | macOSApplicationExtension

平臺(tái)名稱(chēng)watchOS

平臺(tái)名稱(chēng)tvOS

platform-version

平臺(tái)版本十進(jìn)制數(shù)字

平臺(tái)版本十進(jìn)制數(shù)字 . 十進(jìn)制數(shù)字

平臺(tái)版本十進(jìn)制數(shù)字 . 十進(jìn)制數(shù)字 . 十進(jìn)制數(shù)字

? 表達(dá)式 聲明 ?
?