在 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ǔ)句
循環(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ǔ)法
循環(huán)語(yǔ)句 → for-in 語(yǔ)句
循環(huán)語(yǔ)句 → while 語(yǔ)句
循環(huán)語(yǔ)句 → repeat-while 語(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ǔ)法
只要循環(huán)條件為真,while
語(yǔ)句就會(huì)重復(fù)執(zhí)行代碼塊。
while
語(yǔ)句的形式如下:
while condition {
statements
}
while
語(yǔ)句的執(zhí)行流程如下:
condition
)的值。如果為 true
,轉(zhuǎn)到第 2 步;如果為 false
,while
語(yǔ)句至此執(zhí)行完畢。由于會(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ǔ)法
repeat-while
語(yǔ)句至少執(zhí)行一次代碼塊,之后只要循環(huán)條件為真,就會(huì)重復(fù)執(zhí)行代碼塊。
repeat-while
語(yǔ)句的形式如下:
repeat {
statements
} while condition
repeat-while
語(yǔ)句的執(zhí)行流程如下:
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ǔ)法
分支語(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ǔ)法
分支語(yǔ)句 → if 語(yǔ)句
分支語(yǔ)句 → guard 語(yǔ)句
分支語(yǔ)句 → switch 語(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ǔ)法
如果一個(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ǔ)法
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í)行。
在 Swift 中,switch
語(yǔ)句中控制表達(dá)式的每一個(gè)可能的值都必須至少有一個(gè) case
與之對(duì)應(yīng)。在某些無(wú)法面面俱到的情況下(例如,表達(dá)式的類(lèi)型是 Int
),你可以使用 default
分支滿足該要求。
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 語(yǔ)句 → switch 表達(dá)式 { switch-case 列表可選 }
switch case 列表 → switch-case switch-case 列表可選
switch case → case 標(biāo)簽 多條語(yǔ)句 | default 標(biāo)簽 多條語(yǔ)句 | conditional-switch-case
case 標(biāo)簽 → 屬性可選 case case 項(xiàng)列表 :
case 項(xiàng)列表 → 模式 where 子句可選 | 模式 where 子句可選 , case 項(xiàng)列表
default 標(biāo)簽 → 屬性可選 default :
where-clause → where where 表達(dá)式
where-expression → 表達(dá)式
conditional-switch-case → switch-if-directive-clause switch-elseif-directive-clauses 可選 switch-else-directive-clause 可選 endif-directive
switch-if-directive 語(yǔ)句 → if-directive compilation-condition switch-cases 可選
switch-elseif-directive 語(yǔ)句(復(fù)數(shù)) → elseif-directive-clause switch-elseif-directive-clauses可選
switch-elseif-directive 語(yǔ)句 → elseif-directive compilation-condition switch-cases可選
switch-else-directive 語(yǔ)句 → else-directive switch-cases 可選
你可以在循環(huán)語(yǔ)句或 switch
語(yǔ)句前面加上標(biāo)簽,它由標(biāo)簽名和緊隨其后的冒號(hào)(:
)組成。在 break
和 continue
后面跟上標(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ǔ)法
帶標(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ǔ)句
語(yǔ)句標(biāo)簽 → 標(biāo)簽名稱(chēng) :
標(biāo)簽名稱(chēng) → 標(biāo)識(shí)符
控制轉(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ǔ)法
控制轉(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ǔ)句用于終止循環(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 語(yǔ)句 → break 標(biāo)簽名稱(chēng)可選
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 語(yǔ)句 → continue 標(biāo)簽名稱(chēng)可選
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 語(yǔ)句 → fallthrough
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 語(yǔ)句 → return 表達(dá)式可選
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 語(yǔ)句 → throw 表達(dá)式
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ǔ)法
延遲語(yǔ)句 → defer 代碼塊
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 語(yǔ)句 → do 代碼塊 多條 catch 子句可選
多條 catch 子句 → catch 子句 多條 catch 子句可選
編譯器控制語(yǔ)句允許程序改變編譯器的行為。Swift 有三種編譯器控制語(yǔ)句:條件編譯語(yǔ)句、線路控制語(yǔ)句和編譯時(shí)診斷語(yǔ)句。
編譯器控制語(yǔ)句語(yǔ)法
編譯器控制語(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í)行。
編譯配置可以是 true
和 false
的字面量,也可以是使用 -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ǔ)法。
條件編譯代碼塊語(yǔ)法
條件編譯代碼塊 → if-directive 語(yǔ)句 elseif-directive 語(yǔ)句(復(fù)數(shù))可選 else-directive 語(yǔ)句可選 endif-directive
if-directive 語(yǔ)句 → if-directive 編譯條件 語(yǔ)句(復(fù)數(shù))可選
elseif-directive 語(yǔ)句(復(fù)數(shù)) → elseif-directive 語(yǔ)句 elseif-directive 語(yǔ)句(復(fù)數(shù))
elseif-directive 語(yǔ)句 → elseif-directive 編譯條件 語(yǔ)句(復(fù)數(shù))可選
else-directive 語(yǔ)句 → else-directive 語(yǔ)句(復(fù)數(shù))可選
if-directive → #if
elseif-directive → #elseif
else-directive → #else
endif-directive → #endif
編譯條件 → 平臺(tái)條件
編譯條件 → 標(biāo)識(shí)符
編譯條件 → 布爾值字面量
編譯條件 → ( 編譯條件 )
編譯條件 → ! 編譯條件
平臺(tái)條件 → os ( 操作系統(tǒng) )
平臺(tái)條件 → arch ( 架構(gòu) )
平臺(tái)條件 → compiler ( >= swift 版本 ) | compiler ( < swift 版本 )
平臺(tái)條件 → canImport ( 模塊名 )
平臺(tái)條件 → targetEnvironment ( 環(huán)境 )
操作系統(tǒng) → macOS | iOS | watchOS | tvOS
架構(gòu) → i386 | x86_64 | arm | arm64
swift 版本 → 十進(jìn)制數(shù)字 -. -swift 版本延續(xù) 可選
swift 版本延續(xù) → . 十進(jìn)制數(shù)字 swift 版本延續(xù) 可選
模塊名 → identifier
環(huán)境 → 模擬器
行控制語(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)和文件名。
行控制語(yǔ)句語(yǔ)法
行控制語(yǔ)句 → #sourceLocation(file:文件名,line:行號(hào))
行控制語(yǔ)句 → #sourceLocation( )
行號(hào) → 大于 0 的十進(jìn)制整數(shù)
文件名 → 靜態(tài)字符串字面量
編譯時(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ǔ)法
診斷語(yǔ)句 → #error ( 診斷消息 )
診斷語(yǔ)句 → #warning ( 診斷消息 )
診斷語(yǔ)句 → 靜態(tài)字符串字面量
可用性條件可作為 if
,while
,guard
語(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ǔ)法
可用性條件 → #available ( 可用性參數(shù)列表 )
可用性參數(shù)列表 → 可用性參數(shù) | 可用性參數(shù) , 可用性參數(shù)列表
可用性參數(shù) → 平臺(tái)名稱(chēng) 平臺(tái)版本
可用性條件 → *
平臺(tái)名稱(chēng) → iOS | iOSApplicationExtension
平臺(tái)名稱(chēng) → OSX | macOSApplicationExtension
平臺(tái)名稱(chēng) → watchOS
平臺(tái)名稱(chēng) → tvOS
平臺(tái)版本 → 十進(jìn)制數(shù)字
平臺(tái)版本 → 十進(jìn)制數(shù)字 . 十進(jìn)制數(shù)字
平臺(tái)版本 → 十進(jìn)制數(shù)字 . 十進(jìn)制數(shù)字 . 十進(jìn)制數(shù)字