1.0 翻譯:coverxit 校對:numbbbbb, coverxit, stanzhai
2.0 翻譯+校對:littledogboy
2.2 翻譯:chenmingbiao
3.0 翻譯:chenmingjia
本頁包含內(nèi)容:
在 Swift 中,有三種類型的語句:簡單語句、編譯器控制語句和控制流語句。簡單語句是最常見的,用于構(gòu)造表達式或者聲明。編譯器控制語句允許程序改變編譯器的行為,包含編譯配置語句和行控制語句。
控制流語句則用于控制程序執(zhí)行的流程,Swift 中有多種類型的控制流語句:循環(huán)語句、分支語句和控制轉(zhuǎn)移語句。循環(huán)語句用于重復(fù)執(zhí)行代碼塊;分支語句用于執(zhí)行滿足特定條件的代碼塊;控制轉(zhuǎn)移語句則用于改變代碼的執(zhí)行順序。另外,Swift 提供了 do
語句,用于構(gòu)建局部作用域,還用于錯誤的捕獲和處理;還提供了 defer
語句,用于退出當前作用域之前執(zhí)行清理操作。
是否將分號(;
)添加到語句的末尾是可選的。但若要在同一行內(nèi)寫多條獨立語句,則必須使用分號。
語句語法
</a> 語句 → 表達式 ;可選
語句 → 聲明 ;可選
語句 → 循環(huán)語句 ;可選
語句 → 分支語句 ;可選
語句 → 帶標簽的語句 ;可選
語句 → 控制轉(zhuǎn)移語句 ;可選
語句 → defer 語句 ;可選
語句 → do 語句 :可選
語句 → 編譯器控制語句
多條語句 → 語句 多條語句可選
循環(huán)語句會根據(jù)特定的循環(huán)條件來重復(fù)執(zhí)行代碼塊。Swift 提供三種類型的循環(huán)語句:for-in
語句、while
語句和 repeat-while
語句。
通過 break
語句和 continue
語句可以改變循環(huán)語句的控制流。有關(guān)這兩條語句,詳情參見 Break 語句 和 Continue 語句。
循環(huán)語句語法
循環(huán)語句 → for-in 語句
循環(huán)語句 → while 語句
循環(huán)語句 → repeat-while 語句
for-in
語句會為集合(或?qū)崿F(xiàn)了 SequenceType
協(xié)議的任意類型)中的每一項執(zhí)行一次代碼塊。
for-in
語句的形式如下:
for 項 in 集合 {
循環(huán)體語句
}
for-in
語句在循環(huán)開始前會調(diào)用集合表達式的 generate()
方法來獲取一個實現(xiàn)了 GeneratorType
協(xié)議的類型的值。接下來循環(huán)開始,反復(fù)調(diào)用該值的 next()
方法。如果其返回值不是 None
,它將會被賦給“項”,然后執(zhí)行循環(huán)體語句,執(zhí)行完畢后回到循環(huán)開始處,繼續(xù)重復(fù)這一過程;否則,既不會賦值也不會執(zhí)行循環(huán)體語句,for-in
語句至此執(zhí)行完畢。
只要循環(huán)條件為真,while
語句就會重復(fù)執(zhí)行代碼塊。
while
語句的形式如下:
while 條件 {
語句
}
while
語句的執(zhí)行流程如下:
true
,轉(zhuǎn)到第 2 步;如果為 false
,while
語句至此執(zhí)行完畢。由于會在執(zhí)行循環(huán)體中的語句前判斷條件的值,因此循環(huán)體中的語句可能會被執(zhí)行若干次,也可能一次也不會被執(zhí)行。
條件的結(jié)果必須是Bool類型或者Bool的橋接類型。另外,條件語句也可以使用可選綁定,請參閱 可選綁定。
while 語句語法
條件列表 → 條件 | 條件 , 條件列表
</a> 條件 → 表達式 |可用性條件 | case條件 | 可選綁定條件
case 條件 → case 模式 構(gòu)造器
repeat-while
語句至少執(zhí)行一次代碼塊,之后只要循環(huán)條件為真,就會重復(fù)執(zhí)行代碼塊。
repeat-while
語句的形式如下:
repeat {
語句
} while 條件
repeat-while
語句的執(zhí)行流程如下:
true
,重復(fù)第 1 步;如果為 false
,repeat-while
語句至此執(zhí)行完畢。由于條件的值是在循環(huán)體中的語句執(zhí)行后才進行判斷,因此循環(huán)體中的語句至少會被執(zhí)行一次。
條件的結(jié)果必須是Bool類型或者Bool的橋接類型。另外,條件語句也可以使用可選綁定,請參閱 可選綁定。
分支語句會根據(jù)一個或者多個條件來執(zhí)行指定部分的代碼。分支語句中的條件將會決定程序如何分支以及執(zhí)行哪部分代碼。Swift 提供兩種類型的分支語句:if
語句和 switch
語句。
if
語句和 switch
語句中的控制流可以用 break
語句改變,請參閱 Break 語句。
if
語句會根據(jù)一個或多個條件來決定執(zhí)行哪一塊代碼。
if
語句有兩種基本形式,無論哪種形式,都必須有花括號。
第一種形式是當且僅當條件為真時執(zhí)行代碼,像下面這樣:
if 條件 {
語句
}
第二種形式是在第一種形式的基礎(chǔ)上添加 else
語句,當只有一個 else
語句時,像下面這樣:
if 條件 {
若條件為真則執(zhí)行這部分語句
} else {
若條件為假則執(zhí)行這部分語句
}
else
語句也可包含 if
語句,從而形成一條鏈來測試更多的條件,像下面這樣:
if 條件1 {
若條件1為真則執(zhí)行這部分語句
} else if 條件2 {
若條件2為真則執(zhí)行這部分語句
} else {
若前兩個條件均為假則執(zhí)行這部分語句
}
if
語句中條件的結(jié)果必須是Bool類型或者Bool的橋接類型。另外,條件語句也可以使用可選綁定,請參閱 可選綁定。
if 語句語法
</a> if 語句 → if 條件子句 代碼塊 else子句可選
else 子句 → else 代碼塊 | else if語句
如果一個或者多個條件不成立,可用 guard
語句用來退出當前作用域。
guard
語句的格式如下:
guard 條件 else {
語句
}
guard
語句中條件的結(jié)果必須是Bool類型或者Bool的橋接類型。另外,條件也可以是一條可選綁定,請參閱 可選綁定。
在 guard
語句中進行可選綁定的常量或者變量,其可用范圍從聲明開始直到作用域結(jié)束。
guard
語句必須有 else
子句,而且必須在該子句中調(diào)用 Never
返回類型的函數(shù),或者使用下面的語句退出當前作用域:
return
break
continue
throw
關(guān)于控制轉(zhuǎn)移語句,請參閱 控制轉(zhuǎn)移語句。關(guān)于Never
返回類型的函數(shù),請參閱 永不返回的函數(shù)。
switch
語句會根據(jù)控制表達式的值來決定執(zhí)行哪部分代碼。
switch
語句的形式如下:
switch 控制表達式 {
case 模式1:
語句
case 模式2 where 條件:
語句
case 模式3 where 條件, 模式4 where 條件:
語句
default:
語句
}
switch
語句會先計算控制表達式的值,然后與每一個 case
的模式進行匹配。如果匹配成功,程序?qū)?zhí)行對應(yīng)的 case
中的語句。另外,每一個 case
都不能為空,也就是說在每一個 case
中必須至少有一條語句。如果你不想在匹配到的 case
中執(zhí)行代碼,只需在該 case
中寫一條 break
語句即可。
可以用作控制表達式的值是十分靈活的。除了標量類型外,如 Int
、Character
,你可以使用任何類型的值,包括浮點數(shù)、字符串、元組、自定義類型的實例和可選類型??刂票磉_式的值還可以用來匹配枚舉類型中的成員值或是檢查該值是否包含在指定的 Range
中。關(guān)于如何在 switch
語句中使用這些類型,請參閱 控制流 一章中的 Switch。
每個 case
的模式后面可以有一個 where
子句。where
子句由 where
關(guān)鍵字緊跟一個提供額外條件的表達式組成。因此,當且僅當控制表達式匹配一個 case
的模式且 where
子句的表達式為真時,case
中的語句才會被執(zhí)行。在下面的例子中,控制表達式只會匹配包含兩個相等元素的元組,例如 (1, 1)
:
case let (x, y) where x == y:
正如上面這個例子,也可以在模式中使用 let
(或 var
)語句來綁定常量(或變量)。這些常量(或變量)可以在對應(yīng)的 where
子句以及 case
中的代碼中使用。但是,如果一個 case
中含有多個模式,所有的模式必須包含相同的常量(或變量)綁定,并且每一個綁定的常量(或變量)必須在所有的條件模式中都有相同的類型。
switch
語句也可以包含默認分支,使用 default
關(guān)鍵字表示。只有所有 case
都無法匹配控制表達式時,默認分支中的代碼才會被執(zhí)行。一個 switch
語句只能有一個默認分支,而且必須在 switch
語句的最后面。
switch
語句中 case
的匹配順序和源代碼中的書寫順序保持一致。因此,當多個模式都能匹配控制表達式時,只有第一個匹配的 case
中的代碼會被執(zhí)行。
在 Swift 中,switch
語句中控制表達式的每一個可能的值都必須至少有一個 case
與之對應(yīng)。在某些無法面面俱到的情況下(例如,表達式的類型是 Int
),你可以使用 default
分支滿足該要求。
當匹配到的 case
中的代碼執(zhí)行完畢后,switch
語句會直接退出,而不會繼續(xù)執(zhí)行下一個 case
。這就意味著,如果你想執(zhí)行下一個 case
,需要顯式地在當前 case
中使用 fallthrough
語句。關(guān)于 fallthrough
語句的更多信息,請參閱 Fallthrough 語句。
switch 語句語法
switch 語句 → switch 表達式 { switch-case列表可選 }
</a> switch case 列表 → switch-case switch-case列表可選
switch case → case標簽 多條語句 | default標簽 多條語句
case 標簽 → case case項列表 :
</a> case 項列表 → 模式 where子句可選 | 模式 where子句可選 , case項列表
default 標簽 → default :
你可以在循環(huán)語句或 switch
語句前面加上標簽,它由標簽名和緊隨其后的冒號(:
)組成。在 break
和 continue
后面跟上標簽名可以顯式地在循環(huán)語句或 switch
語句中改變相應(yīng)的控制流。關(guān)于這兩條語句用法,請參閱 Break 語句 和 Continue 語句。
標簽的作用域在該標簽所標記的語句內(nèi)??梢郧短资褂脦撕灥恼Z句,但標簽名必須唯一。
關(guān)于使用帶標簽的語句的例子,請參閱 控制流 一章中的 帶標簽的語句。
帶標簽的語句語法
</a> 帶標簽的語句 → 語句標簽 循環(huán)語句 | 語句標簽 if語句 | 語句標簽 switch語句
語句標簽 → 標簽名稱 :
標簽名稱 → 標識符
控制轉(zhuǎn)移語句能夠無條件地把控制權(quán)從一片代碼轉(zhuǎn)移到另一片代碼,從而改變代碼執(zhí)行的順序。Swift 提供五種類型的控制轉(zhuǎn)移語句:break
語句、continue
語句、fallthrough
語句、return
語句和 throw
語句。
控制轉(zhuǎn)移語句語法
控制轉(zhuǎn)移語句 → break 語句
控制轉(zhuǎn)移語句 → continue 語句
控制轉(zhuǎn)移語句 → fallthrough 語句
控制轉(zhuǎn)移語句 → return 語句
控制轉(zhuǎn)移語句 → throw 語句
break
語句用于終止循環(huán)語句、if
語句或 switch
語句的執(zhí)行。使用 break
語句時,可以只寫 break
這個關(guān)鍵詞,也可以在 break
后面跟上標簽名,像下面這樣:
break
break標簽名
當 break
語句后面帶標簽名時,可用于終止由這個標簽標記的循環(huán)語句、if
語句或 switch
語句的執(zhí)行。
而只寫 break
時,則會終止 switch
語句或 break
語句所屬的最內(nèi)層循環(huán)語句的執(zhí)行。不能使用 break
語句來終止未使用標簽的 if
語句。
無論哪種情況,控制權(quán)都會被轉(zhuǎn)移給被終止的控制流語句后面的第一行語句。
關(guān)于使用 break
語句的例子,請參閱 控制流 一章的 Break 和 帶標簽的語句。
break 語句語法
break 語句 → break 標簽名稱可選
continue
語句用于終止循環(huán)中當前迭代的執(zhí)行,但不會終止該循環(huán)的執(zhí)行。使用 continue
語句時,可以只寫 continue
這個關(guān)鍵詞,也可以在 continue
后面跟上標簽名,像下面這樣:
continue
continue標簽名
當 continue
語句后面帶標簽名時,可用于終止由這個標簽標記的循環(huán)中當前迭代的執(zhí)行。
而當只寫 continue
時,可用于終止 continue
語句所屬的最內(nèi)層循環(huán)中當前迭代的執(zhí)行。
在這兩種情況下,控制權(quán)都會被轉(zhuǎn)移給循環(huán)語句的條件語句。
在 for
語句中,continue
語句執(zhí)行后,增量表達式還是會被計算,這是因為每次循環(huán)體執(zhí)行完畢后,增量表達式都會被計算。
關(guān)于使用 continue
語句的例子,請參閱 控制流 一章的 Continue 和 帶標簽的語句。
continue 語句語法
continue 語句 → continue 標簽名稱可選
fallthrough
語句用于在 switch
語句中轉(zhuǎn)移控制權(quán)。fallthrough
語句會把控制權(quán)從 switch
語句中的一個 case
轉(zhuǎn)移到下一個 case
。這種控制權(quán)轉(zhuǎn)移是無條件的,即使下一個 case
的模式與 switch
語句的控制表達式的值不匹配。
fallthrough
語句可出現(xiàn)在 switch
語句中的任意 case
中,但不能出現(xiàn)在最后一個 case
中。同時,fallthrough
語句也不能把控制權(quán)轉(zhuǎn)移到使用了值綁定的 case
。
關(guān)于在 switch
語句中使用 fallthrough
語句的例子,請參閱 控制流 一章的 控制轉(zhuǎn)移語句。
return
語句用于在函數(shù)或方法的實現(xiàn)中將控制權(quán)轉(zhuǎn)移到調(diào)用函數(shù)或方法,接著程序?qū)恼{(diào)用位置繼續(xù)向下執(zhí)行。
使用 return
語句時,可以只寫 return
這個關(guān)鍵詞,也可以在 return
后面跟上表達式,像下面這樣:
return
return表達式
當 return
語句后面帶表達式時,表達式的值將會返回給調(diào)用函數(shù)或方法。如果表達式的值的類型與函數(shù)或者方法聲明的返回類型不匹配,Swift 則會在返回表達式的值之前將表達式的值的類型轉(zhuǎn)換為返回類型。
注意
正如 可失敗構(gòu)造器 中所描述的,return nil
在可失敗構(gòu)造器中用于表明構(gòu)造失敗。
而只寫 return
時,僅僅是從該函數(shù)或方法中返回,而不返回任何值(也就是說,函數(shù)或方法的返回類型為 Void
或者說 ()
)。
return 語句語法
return 語句 → return 表達式可選
throw
語句出現(xiàn)在拋出函數(shù)或者拋出方法體內(nèi),或者類型被 throws
關(guān)鍵字標記的閉包表達式體內(nèi)。
throw
語句使程序在當前作用域結(jié)束執(zhí)行,并向外圍作用域傳播錯誤。拋出的錯誤會一直傳遞,直到被 do
語句的 catch
子句處理掉。
throw
語句由 throw
關(guān)鍵字緊跟一個表達式組成,如下所示:
throw
表達式
表達式的結(jié)果必須符合 ErrorType
協(xié)議。
關(guān)于如何使用 throw
語句的例子,請參閱 錯誤處理 一章的 用 throwing 函數(shù)傳遞錯誤。
throw 語句語法
throw 語句 → throw 表達式
defer
語句用于在退出當前作用域之前執(zhí)行代碼。
defer
語句形式如下:
defer {
語句
}
在 defer
語句中的語句無論程序控制如何轉(zhuǎn)移都會被執(zhí)行。在某些情況下,例如,手動管理資源時,比如關(guān)閉文件描述符,或者即使拋出了錯誤也需要執(zhí)行一些操作時,就可以使用 defer
語句。
如果多個 defer
語句出現(xiàn)在同一作用域內(nèi),那么它們執(zhí)行的順序與出現(xiàn)的順序相反。給定作用域中的第一個 defer
語句,會在最后執(zhí)行,這意味著代碼中最靠后的 defer
語句中引用的資源可以被其他 defer
語句清理掉。
func f() {
defer { print("First") }
defer { print("Second") }
defer { print("Third") }
}
f()
// 打印 “Third”
// 打印 “Second”
// 打印 “First”
defer
語句中的語句無法將控制權(quán)轉(zhuǎn)移到 defer
語句外部。
defer 語句語法
延遲語句 → defer 代碼塊
do
語句用于引入一個新的作用域,該作用域中可以含有一個或多個 catch
子句,catch
子句中定義了一些匹配錯誤條件的模式。do
語句作用域內(nèi)定義的常量和變量只能在 do
語句作用域內(nèi)使用。
Swift 中的 do
語句與 C 中限定代碼塊界限的大括號({}
)很相似,也并不會降低程序運行時的性能。
do
語句的形式如下:
do {
try 表達式
語句
} catch 模式1 {
語句
} catch 模式2 where 條件 {
語句
}
如同 switch
語句,編譯器會判斷 catch
子句是否有遺漏。如果 catch
子句沒有遺漏,則認為錯誤已被處理。否則,錯誤會自動傳遞到外圍作用域,被某個 catch
子句處理掉或者被用 throws
關(guān)鍵字聲明的拋出函數(shù)繼續(xù)向外拋出。
為了確保錯誤已經(jīng)被處理,可以讓 catch
子句使用匹配所有錯誤的模式,如通配符模式(_
)。如果一個 catch
子句不指定一種具體模式,catch
子句會匹配任何錯誤,并綁定到名為 error
的局部常量。有關(guān)在 catch
子句中使用模式的更多信息,請參閱 模式。
關(guān)于如何在 do
語句中使用一系列 catch
子句的例子,請參閱 錯誤處理。
do 語句語法
</a> do 語句 → do 代碼塊 多條 catch子句可選
多條 catch 子句 → catch子句 多條 catch子句可選
catch 子句 → catch 模式可選 where子句可選 代碼塊
編譯器控制語句允許程序改變編譯器的行為。Swift 有兩種編譯器控制語句:編譯配置語句和線路控制語句。
編譯配置語句可以根據(jù)一個或多個配置來有條件地編譯代碼。
每一個編譯配置語句都以 #if
開始,#endif
結(jié)束。如下是一個簡單的編譯配置語句:
#if 編譯配置項
語句
#endif
和 if
語句的條件不同,編譯配置的條件是在編譯時進行判斷的。只有編譯配置在編譯時判斷為 true
的情況下,相應(yīng)的語句才會被編譯和執(zhí)行。
編譯配置可以是 true
和 false
的字面量,也可以是使用 -D
命令行標志的標識符,或者是下列表格中的任意一個平臺檢測函數(shù)。
函數(shù) | 可用參數(shù) |
---|---|
os() |
OSX , iOS , watchOS , tvOS , Linux |
arch() |
i386 , x86_64 , arm , arm64 |
swift() |
>= 后跟版本號 |
swift()
(語言版本檢測函數(shù))的版本號參數(shù)主要由主版本號和次版本號組成并且使用點號(.
)分隔開,>=
和版本號之間不能有空格。
注意
arch(arm)
平臺檢測函數(shù)在 ARM 64 位設(shè)備上不會返回true
。如果代碼在 32 位的 iOS 模擬器上編譯,arch(i386)
平臺檢測函數(shù)會返回true
。
你可以使用邏輯操作符 &&
、||
和 !
來組合多個編譯配置,還可以使用圓括號來進行分組。
就像 if
語句一樣,你可以使用 #elseif
子句來添加任意多個條件分支來測試不同的編譯配置。你也可以使用 #else
子句來添加最終的條件分支。包含多個分支的編譯配置語句例子如下:
#if 編譯配置1
如果編譯配置1成立則執(zhí)行這部分代碼
#elseif 編譯配置2
如果編譯配置2成立則執(zhí)行這部分代碼
#else
如果編譯配置均不成立則執(zhí)行這部分代碼
#endif
注意
即使沒有被編譯,編譯配置中的語句仍然會被解析。然而,唯一的例外是編譯配置語句中包含語言版本檢測函數(shù):僅當Swift
編譯器版本和語言版本檢測函數(shù)中指定的版本號匹配時,語句才會被解析。這種設(shè)定能確保舊的編譯器不會嘗試去解析新 Swift 版本的語法。
編譯配置語句語法
單個編譯配置語句 → #if 編譯配置 語句可選 多個編譯配置elseif子句可選 - 單個編譯配置else子句可選 #endif
</a> 多個編譯配置 elseif 子句 → 單個編譯配置elseif子句 多個編譯配置elseif子句可選
單個編譯配置 elseif 子句 → #elseif 編譯配置 語句可選
單個編譯配置 else 子句 → #else 語句可選
編譯配置 → 平臺檢測函數(shù)
編譯配置 → 語言版本檢測函數(shù)
編譯配置 → 標識符
編譯配置 → 布爾值字面量
編譯配置 → ( 編譯配置 )
編譯配置 → ! 編譯配置
編譯配置 → 編譯配置 && 編譯配置
編譯配置 → 編譯配置 || 編譯配置
平臺檢測函數(shù) → os ( 操作系統(tǒng) )
平臺檢測函數(shù) → arch ( 架構(gòu) )
</a> 語言版本檢測函數(shù) → swift ( >= swift版本 )
操作系統(tǒng) → OSX | iOS | watchOS | tvOS
</a> 架構(gòu) → i386 | x86_64 | arm | arm64
swift 版本 → 十進制數(shù)字 -. -十進制數(shù)字
行控制語句可以為被編譯的源代碼指定行號和文件名,從而改變源代碼的定位信息,以便進行分析和調(diào)試。
行控制語句形式如下:
#sourceLocation(file:
文件名
, line:行號
)#sourceLocation()
第一種的行控制語句會改變該語句之后的代碼中的字面量表達式 #line
和 #file
所表示的值。行號
是一個大于 0 的整形字面量,會改變 #line
表達式的值。文件名
是一個字符串字面量,會改變 #file
表達式的值。
第二種的行控制語句, #sourceLocation()
,會將源代碼的定位信息重置回默認的行號和文件名。
行控制語句語法
行控制語句 → #sourceLocation(file:文件名,line:行號)
行控制語句 → #sourceLocation()
</a> 行號 → 大于 0 的十進制整數(shù)
文件名 → 靜態(tài)字符串字面量
可用性條件可作為 if
,while
,guard
語句的條件,可以在運行時基于特定的平臺參數(shù)來查詢 API 的可用性。
可用性條件的形式如下:
if #available(平臺名稱 版本, ..., *) {
如果 API 可用,則執(zhí)行這部分語句
} else {
如果 API 不可用,則執(zhí)行這部分語句
}
使用可用性條件來執(zhí)行一個代碼塊時,取決于使用的 API 在運行時是否可用,編譯器會根據(jù)可用性條件提供的信息來決定是否執(zhí)行相應(yīng)的代碼塊。
可用性條件使用一系列逗號分隔的平臺名稱和版本。使用 iOS
,OSX
,以及 watchOS
等作為平臺名稱,并寫上相應(yīng)的版本號。*
參數(shù)是必須寫的,用于處理未來的潛在平臺??捎眯詶l件確保了運行時的平臺不低于條件中指定的平臺版本時才執(zhí)行代碼塊。
與布爾類型的條件不同,不能用邏輯運算符 &&
和 ||
組合可用性條件。
可用性條件語法
可用性條件 → #available ( 可用性參數(shù)列表 )
</a> 可用性參數(shù)列表 → 可用性參數(shù) | 可用性參數(shù) , 可用性參數(shù)列表
可用性參數(shù) → 平臺名稱 平臺版本
可用性條件 → *
平臺名稱 → iOS | iOSApplicationExtension
平臺名稱 → OSX | OSXApplicationExtension
平臺名稱 → watchOS
平臺版本 → 十進制數(shù)字
平臺版本 → 十進制數(shù)字 . 十進制數(shù)字
平臺版本 → 十進制數(shù)字 . 十進制數(shù)字 . 十進制數(shù)字