簡介
Swift 是一門全新的用于開發(fā) iOS, OS X 以及 watchOS 應用的編程語言。
Swift 為所有 C 和 Objective-C 的類型提供了自己的版本,包括整型值的 Int 件余,浮點數(shù)值的 Double 和 Float ,布爾量值的 Bool 嫩实,字符串值的 String 。如同集合類型中描述的那樣窥岩, Swift 同樣也為三個主要的集合類型提供了更高效的版本甲献, Array , Set 和 Dictionary 谦秧。
和 C 一樣竟纳,Swift 用變量存儲和調(diào)用值撵溃,通過變量名來做區(qū)分。Swift 中也大量采用了值不可變的變量锥累。它們就是所謂的常量缘挑,但是它們比 C 中的常量更加給力。當你所處理的值不需要更改時桶略,使用常量會讓你的代碼更加安全语淘、簡潔地表達你的意圖。
除了我們熟悉的類型以外际歼,Swift 還增加了 Objective-C 中沒有的類型惶翻,比如元組。元組允許你來創(chuàng)建和傳遞一組數(shù)據(jù)鹅心。你可以利用元組在一個函數(shù)中以單個復合值的形式返回多個值吕粗。
Swift 還增加了可選項,用來處理沒有值的情況旭愧÷睿可選項意味著要么“這里有一個值,它等于 x”要么“這里根本沒有值”输枯∫楸茫可選項類似于 Objective-C 中的 nil 指針,但是不只是類桃熄,可選項也可以用在所有的類型上先口。可選項比 Objective-C 中的 nil 指針更安全瞳收、更易讀碉京,他也是 Swift 語言中許多重要功能的核心。
可選項充分證明了 Swift 是一門類型安全的語言螟深。Swift 幫助你明確代碼可以操作值的類型收夸。如果你的一段代碼預期得到一個 String ,類型會安全地阻止你不小心傳入 Int 血崭。在開發(fā)過程中,這個限制能幫助你在開發(fā)過程中更早地發(fā)現(xiàn)并修復錯誤厘灼。
常量和變量
聲明
使用let聲明一個常量夹纫,使用var聲明一個變量。
let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0
你可以在一行中聲明多個變量或常量设凹,用逗號分隔:
var x = 0.0, y = 0.0, z = 0.0
類型標注
你可以在聲明一個變量或常量的時候提供類型標注舰讹,來明確變量或常量能夠儲存值的類型。添加類型標注的方法是在變量或常量的名字后邊加一個冒號闪朱,再跟一個空格月匣,最后加上要使用的類型名稱钻洒。
var welcomeMessage: String
let welcomeMessage: String
你可以在一行中定義多個相關(guān)的變量為相同的類型,用逗號分隔锄开,只要在最后的變量名字后邊加上類型標注素标。
var red, green, blue: Double
命名
常量和變量的名字幾乎可以使用任何字符,甚至包括 Unicode 字符:
let π = 3.14159
let 你好 = "你好世界"
let ?????? = "dogcow"
常量和變量的名字不能包含空白字符萍悴、數(shù)學符號头遭、箭頭、保留的(或者無效的)Unicode 碼位癣诱、連線和制表符计维。也不能以數(shù)字開頭,盡管數(shù)字幾乎可以使用在名字其他的任何地方撕予。
一旦你聲明了一個確定類型的常量或者變量鲫惶,就不能使用相同的名字再次進行聲明,也不能讓它改存其他類型的值实抡。常量和變量之間也不能互換欠母。
如果你需要使用 Swift 保留的關(guān)鍵字來給常量或變量命名,可以使用反引號( ` )包圍它來作為名稱澜术∫蘸總之,除非別無選擇鸟废,避免使用關(guān)鍵字作為名字除非你確實別無選擇猜敢。
輸出
你可以使用 print(_:separator:terminator:) 函數(shù)來打印當前常量和變量中的值。
print(friendlyWelcome)
// 輸出 "Bonjour!"
注釋
使用注釋來將不需要執(zhí)行的文本放入的代碼當中盒延,作為標記或者你自己的提醒缩擂。當 Swift 編譯器在編譯代碼的時候會忽略掉你的注釋。
Swift 中的注釋和 C 的注釋基本相同添寺。單行注釋用兩個斜杠開頭( // ):
// 這是一個注釋
多行的注釋以一個斜杠加一個星號開頭( /* )胯盯,以一個星號加斜杠結(jié)尾( */ )。
/* this is also a comment,
but written over multiple lines */
和 C 中的多行注釋不同的是计露, Swift 語言中的多行的注釋可以內(nèi)嵌在其它的多行注釋之中博脑,你可以在多行注釋中先開啟一個注釋塊,接著再開啟另一個注釋塊票罐。然后關(guān)閉第二個注釋塊叉趣,再關(guān)閉第一個注釋塊。
/* 這是第一個多行注釋的開頭
/* 這是第二個嵌套在內(nèi)的注釋塊 */
這是第一個注釋塊的結(jié)尾*/
內(nèi)嵌多行注釋该押,可以便捷地注釋掉一大段代碼塊疗杉,即使這段代碼塊中已經(jīng)有了多行注釋。
分號
和許多其他的語言不同蚕礼,Swift 并不要求你在每一句代碼結(jié)尾寫分號( ; )烟具,當然如果你想寫的話也沒問題梢什。總之朝聋,如果你想在一行里寫多句代碼嗡午,分號還是需要的。
let cat = "???"; print(cat)
// 輸出 "???"
整數(shù)
Swift 提供了 8玖翅,16翼馆,32 和 64 位編碼的有符號和無符號整數(shù),這些整數(shù)類型的命名方式和 C 相似金度,例如 8 位無符號整數(shù)的類型是 UInt8 应媚,32 位有符號整數(shù)的類型是 Int32 。與 Swift 中的其他類型相同猜极,這些整數(shù)類型也用開頭大寫命名法中姜。
范圍
你可以通過 min 和 max 屬性來訪問每個整數(shù)類型的最小值和最大值:
let minValue = UInt8.min // 最小值是 0, 值的類型是 UInt8
let maxValue = UInt8.max // 最大值是 255, 值得類型是 UInt8
Int
在大多數(shù)情況下,你不需要在你的代碼中為整數(shù)設置一個特定的長度跟伏。Swift 提供了一個額外的整數(shù)類型: Int 丢胚,它擁有與當前平臺的原生字相同的長度。
- 在32位平臺上受扳, Int 的長度和 Int32 相同携龟。
- 在64位平臺上, Int 的長度和 Int64 相同勘高。
除非你需操作特定長度的整數(shù)峡蟋,否則請盡量在代碼中使用 Int 作為你的整數(shù)的值類型。這樣能提高代碼的統(tǒng)一性和兼容性华望,即使在 32 位的平臺上蕊蝗, Int 也可以存 -2,147,483,648 到 2,147,483,647 之間的任意值,對于大多數(shù)整數(shù)區(qū)間來說完全夠用了赖舟。
UInt
Swift 也提供了一種無符號的整數(shù)類型蓬戚, UInt ,它和當前平臺的原生字長度相同宾抓。
- 在32位平臺上子漩, UInt 長度和 UInt32 長度相同。
- 在64位平臺上石洗, UInt 長度和 UInt64 長度相同痛单。
只在的確需要存儲一個和當前平臺原生字長度相同的無符號整數(shù)的時候才使用 UInt 。其他情況下劲腿,推薦使用 Int ,即使已經(jīng)知道存儲的值都是非負的鸟妙。如同類型安全和類型推斷中描述的那樣焦人,統(tǒng)一使用 Int 會提高代碼的兼容性挥吵,同時可以避免不同數(shù)字類型之間的轉(zhuǎn)換問題,也符合整數(shù)的類型推斷花椭。
浮點數(shù)
浮點數(shù)是有小數(shù)的數(shù)字忽匈,比如 3.14159 , 0.1 , 和 -273.15 。
浮點類型相比整數(shù)類型來說能表示更大范圍的值矿辽,可以存儲比 Int 類型更大或者更小的數(shù)字丹允。Swift 提供了兩種有符號的浮點數(shù)類型。
- Double代表 64 位的浮點數(shù)袋倔。
- Float 代表 32 位的浮點數(shù)雕蔽。
Double 有至少 15 位數(shù)字的精度,而 Float 的精度只有 6 位宾娜。具體使用哪種浮點類型取決于你代碼需要處理的值范圍批狐。在兩種類型都可以的情況下,推薦使用 Double 類型前塔。
類型安全和類型推斷
Swift 是一門類型安全的語言嚣艇。類型安全的語言可以讓你清楚地知道代碼可以處理的值的類型。如果你的一部分代碼期望獲得 String 华弓,你就不能錯誤的傳給它一個 Int 食零。
因為 Swift 是類型安全的,他在編譯代碼的時候會進行類型檢查寂屏,任何不匹配的類型都會被標記為錯誤贰谣。這會幫助你在開發(fā)階段更早的發(fā)現(xiàn)并修復錯誤。
數(shù)值型字面量
整數(shù)型字面量可以寫作:
- 一個十進制數(shù)凑保,沒有前綴
- 一個二進制數(shù)冈爹,前綴是 0b
- 一個八進制數(shù),前綴是 0o
- 一個十六進制數(shù)欧引,前綴是 0x
下面的這些所有整數(shù)字面量的十進制值都是 17
let decimalInteger = 17
let binaryInteger = 0b10001 // 17 in binary notation
let octalInteger = 0o21 // 17 in octal notation
let hexadecimalInteger = 0x11 // 17 in hexadecimal notation
數(shù)值類型轉(zhuǎn)換
整數(shù)轉(zhuǎn)換
要將一種數(shù)字類型轉(zhuǎn)換成另外一種類型频伤,你需要用當前值來初始化一個期望的類型。在下面的栗子中芝此,常量 twoThousand 的類型是 UInt16 憋肖,而常量 one 的類型是 UInt8 。他們不能直接被相加在一起婚苹,因為他們的類型不同岸更。所以,這里讓 UInt16 (one ) 創(chuàng)建一個新的 UInt16 類型并用 one 的值初始化膊升,這樣就可以在原來的地方使用了怎炊。
let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)
因為加號兩邊的類型現(xiàn)在都是 UInt16 ,所以現(xiàn)在是可以相加的。輸出的常量( twoThousandAndOne )被推斷為 UInt16 類型评肆,因為他是兩個 UInt16 類型的和债查。
SomeType(ofInitialValue) 是調(diào)用 Swift 類型初始化器并傳入一個初始值的默認方法。在語言的內(nèi)部瓜挽, UInt16 有一個初始化器盹廷,可以接受一個 UInt8 類型的值,所以這個初始化器可以用現(xiàn)有的 UInt8來創(chuàng)建一個新的 UInt16 久橙。這里需要注意的是并不能傳入任意類型的值俄占,只能傳入 UInt16 內(nèi)部有對應初始化器的值。不過你可以擴展現(xiàn)有的類型來讓它可以接收其他類型的值(包括自定義類型)淆衷,請參考擴展缸榄。
整數(shù)和浮點數(shù)轉(zhuǎn)換
整數(shù)和浮點數(shù)類型的轉(zhuǎn)換必須顯式地指定類型:
let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi equals 3.14159, and is inferred to be of type Double
在這里,常量 three 的值被用來創(chuàng)建一個類型為 Double 的新的值吭敢,所以加號兩邊的值的類型是相同的碰凶。沒有這個轉(zhuǎn)換,加法就無法進行鹿驼。
類型別名
類型別名可以為已經(jīng)存在的類型定義了一個新的可選名字欲低。用 typealias 關(guān)鍵字定義類型別名。
當你根據(jù)上下文的語境想要給類型一個更有意義的名字的時候畜晰,類型別名會非常高效砾莱,例如處理外部資源中特定長度的數(shù)據(jù)時:
typealias AudioSample = UInt16
布爾值
Swift 有一個基礎的布爾量類型,就是 Bool 凄鼻,布爾量被作為邏輯值來引用腊瑟,因為他的值只能是真或者假。Swift為布爾量提供了兩個常量值块蚌, true 和 false 闰非。
let orangesAreOrange = true
let turnipsAreDelicious = false
Swift 的類型安全機制會阻止你用一個非布爾量的值替換掉 Bool 。下面的栗子中報告了一個發(fā)生在編譯時的錯誤:
let i = 1
if i {
// this example will not compile, and will report an error
}
let i = 1
if i == 1 {
// this example will compile successfully
}
元組
元組把多個值合并成單一的復合型的值峭范。元組內(nèi)的值可以是任何類型财松,而且可以不必是同一類型。
在下面的示例中纱控, (404, "Not Found") 是一個描述了 HTTP 狀態(tài)代碼 的元組辆毡。HTTP 狀態(tài)代碼是當你請求網(wǎng)頁的時候 web 服務器返回的一個特殊值。當你請求不存在的網(wǎng)頁時甜害,就會返回 404 Not Found
let http404Error = (404, "Not Found")
// http404Error is of type (Int, String), and equals (404, "Not Found")
(404, "Not Found")元組把一個 Int 和一個 String 組合起來表示 HTTP 狀態(tài)代碼的兩種不同的值:數(shù)字和人類可讀的描述舶掖。他可以被描述為“一個類型為 (Int, String) 的元組”
任何類型的排列都可以被用來創(chuàng)建一個元組,他可以包含任意多的類型尔店。例如 (Int, Int, Int) 或者 (String, Bool) 眨攘,實際上主慰,任何類型的組合都是可以的。
你也可以將一個元組的內(nèi)容分解成單獨的常量或變量期犬,這樣你就可以正常的使用它們了:
let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)")
// prints "The status code is 404"
print("The status message is \(statusMessage)")
// prints "The status message is Not Found"
當你分解元組的時候河哑,如果只需要使用其中的一部分數(shù)據(jù),不需要的數(shù)據(jù)可以用下滑線( _ )代替:
let (justTheStatusCode, _) = http404Error
print("The status code is \(justTheStatusCode)")
// prints "The status code is 404"
另外一種方法就是利用從零開始的索引數(shù)字訪問元組中的單獨元素:
print("The status code is \(http404Error.0)")
// prints "The status code is 404"
print("The status message is \(http404Error.1)")
// prints "The status message is Not Found"
你可以在定義元組的時候給其中的單個元素命名:
let http200Status = (statusCode: 200, description: "OK")
在命名之后龟虎,你就可以通過訪問名字來獲取元素的值了:
print("The status code is \(http200Status.statusCode)")
// prints "The status code is 200"
print("The status message is \(http200Status.description)")
// prints "The status message is OK"
作為函數(shù)返回值時,元組非常有用沙庐。一個用來獲取網(wǎng)頁的函數(shù)可能會返回一個 (Int, String) 元組來描述是否獲取成功鲤妥。相比只能返回一個類型的值,元組能包含兩個不同類型值拱雏,他可以讓函數(shù)的返回信息更有用棉安。更多內(nèi)容請參考多返回值的函數(shù)。
可選項
可以利用可選項來處理值可能缺失的情況铸抑。
在 C 和 Objective-C 中贡耽,沒有可選項的概念。在 Objective-C 中有一個近似的特性鹊汛,一個方法可以返回一個對象或者返回 nil 蒲赂。 nil 的意思是“缺少一個可用對象”。然而刁憋,他只能用在對象上滥嘴,卻不能作用在結(jié)構(gòu)體,基礎的 C 類型和枚舉值上至耻。對于這些類型若皱,Objective-C 會返回一個特殊的值(例如 NSNotFound )來表示值的缺失。這種方法是建立在假設調(diào)用者知道這個特殊的值并記得去檢查他尘颓。然而走触,Swift 中的可選項就可以讓你知道任何類型的值的缺失,他并不需要一個特殊的值
下面的栗子演示了可選項如何作用于值的缺失疤苹,Swift 的 Int 類型中有一個初始化器互广,可以將 String 值轉(zhuǎn)換為一個 Int 值。然而并不是所有的字符串都可以轉(zhuǎn)換成整數(shù)痰催。字符串 “123” 可以被轉(zhuǎn)換為數(shù)字值 123 兜辞,但是字符串 "hello, world" 就顯然不能轉(zhuǎn)換為一個數(shù)字值。
在下面的栗子中夸溶,試圖利用初始化器將一個 String 轉(zhuǎn)換為 Int :
et possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumber is inferred to be of type "Int?", or "optional Int"
因為這個初始化器可能會失敗逸吵,所以他會返回一個可選的 Int ,而不是 Int 缝裁∩ㄖ澹可選的 Int 寫做 Int? 足绅,而不是 Int 。問號明確了它儲存的值是一個可選項韩脑,意思就是說它可能包含某些 Int 值氢妈,或者可能根本不包含值段多。(他不能包含其他的值首量,例如 Bool 值或者 String 值。它要么是 Int 要么什么都沒有进苍。)
nil
你可以通過給可選變量賦值一個 nil 來將之設置為沒有值:
var serverResponseCode: Int? = 404
// serverResponseCode contains an actual Int value of 404
serverResponseCode = nil
// serverResponseCode now contains no value
如果你定義的可選變量沒有提供一個默認值加缘,變量會被自動設置成 nil 。
var surveyAnswer: String?
Swift 中的 nil 和Objective-C 中的 nil 不同觉啊,在 Objective-C 中 nil 是一個指向不存在對象的指針拣宏。在 Swift中, nil 不是指針杠人,他是值缺失的一種特殊類型勋乾,任何類型的可選項都可以設置成 nil 而不僅僅是對象類型。
If 語句以及強制展開
你可以利用 if 語句通過比較 nil 來判斷一個可選中是否包含值嗡善。利用相等運算符 ( == )和不等運算符( != )辑莫。
如果一個可選有值,他就“不等于” nil :
if convertedNumber != nil {
print("convertedNumber contains some integer value.")
}
// prints "convertedNumber contains some integer value."
一旦你確定可選中包含值滤奈,你可以在可選的名字后面加一個感嘆號 ( ! ) 來獲取值摆昧,感嘆號的意思就是說“我知道這個可選項里邊有值,展開吧蜒程∩鹉悖”這就是所謂的可選值的強制展開。
if convertedNumber != nil {
print("convertedNumber has an integer value of \(convertedNumber!).")
}
// prints "convertedNumber has an integer value of 123."
可選項綁定
可以使用可選項綁定來判斷可選項是否包含值昭躺,如果包含就把值賦給一個臨時的常量或者變量忌锯。可選綁定可以與 if 和 while 的語句使用來檢查可選項內(nèi)部的值领炫,并賦值給一個變量或常量偶垮。 if 和 while 語句的更多詳細描述,請參考控制流帝洪。
在 if 語句中似舵,這樣書寫可選綁定:
if let constantName = someOptional {
statements
}
if let actualNumber = Int(possibleNumber) {
print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")
} else {
print("\'\(possibleNumber)\' could not be converted to an integer")
}
// prints "'123' has an integer value of 123"
你可以在同一個 if 語句中包含多可選項綁定,用逗號分隔即可葱峡。如果任一可選綁定結(jié)果是 nil 或者布爾值為 false 砚哗,那么整個 if 判斷會被看作 false 。下面的兩個 if 語句是等價的:
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) < 100")
}
// Prints "4 < 42 < 100"
if let firstNumber = Int("4") {
if let secondNumber = Int("42") {
if firstNumber < secondNumber && secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) < 100")
}
}
}
// Prints "4 < 42 < 100"
如同提前退出中描述的那樣砰奕,使用 if 語句創(chuàng)建的常量和變量只在if語句的函數(shù)體內(nèi)有效蛛芥。相反提鸟,在 guard 語句中創(chuàng)建的常量和變量在 guard 語句后的代碼中也可用。
隱式展開可選項
如上所述仅淑,可選項明確了常量或者變量可以“沒有值”称勋。可選項可以通過 if 語句來判斷是否有值涯竟,如果有值的話可以通過可選項綁定來獲取里邊的值赡鲜。
有時在一些程序結(jié)構(gòu)中可選項一旦被設定值之后,就會一直擁有值庐船。在這種情況下蝗蛙,就可以去掉檢查的需求,也不必每次訪問的時候都進行展開醉鳖,因為它可以安全的確認每次訪問的時候都有一個值。
這種類型的可選項被定義為隱式展開可選項哮内。通過在聲明的類型后邊添加一個嘆號( String! )而非問號( String? )來書寫隱式展開可選項盗棵。與在使用可選項時在名稱后加一個嘆號不同的是,聲明的時候要把嘆號放在類型的后面北发。
在可選項被定義的時候就能立即確認其中有值的情況下纹因,隱式展開可選項非常有用。如同無主引用和隱式展開的可選屬性中描述的那樣琳拨,隱式展開可選項主要被用在 Swift 類的初始化過程中瞭恰。
隱式展開可選項是后臺場景中通用的可選項,但是同樣可以像非可選值那樣來使用狱庇,每次訪問的時候都不需要展開惊畏。下面的栗子展示了在訪問被明確為 String 的可選項展開值時,可選字符串和隱式展開可選字符串的行為區(qū)別:
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark
let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // no need for an exclamation mark
錯誤處理
在程序執(zhí)行階段密任,你可以使用錯誤處理機制來為錯誤狀況負責颜启。
相比于可選項的通過值是否缺失來判斷程序的執(zhí)行正確與否,而錯誤處理機制能允許你判斷錯誤的形成原因浪讳,在必要的情況下缰盏,還能將你的代碼中的錯誤傳遞到程序的其他地方。
當一個函數(shù)遇到錯誤情況淹遵,他會拋出一個錯誤口猜,這個函數(shù)的訪問者會捕捉到這個錯誤,并作出合適的反應透揣。
func canThrowAnError() throws {
// this function may or may not throw an error
}
通過在函數(shù)聲明過程當中加入 throws 關(guān)鍵字來表明這個函數(shù)會拋出一個錯誤济炎。當你調(diào)用了一個可以拋出錯誤的函數(shù)時,需要在表達式前預置 try 關(guān)鍵字淌实。
Swift 會自動將錯誤傳遞到它們的生效范圍之外冻辩,直到它們被 catch 分句處理猖腕。
do {
try canThrowAnError()
// no error was thrown
} catch {
// an error was thrown
}
do 語句創(chuàng)建了一個新的容器范圍,可以讓錯誤被傳遞到到不止一個的 catch 分句里恨闪。
func makeASandwich() throws {
// ...
}
do {
try makeASandwich()
eatASandwich()
} catch Error.OutOfCleanDishes {
washDishes()
} catch Error.MissingIngredients(let ingredients) {
buyGroceries(ingredients)
}
在上面的栗子中倘感,在沒有干凈的盤子或者缺少原料的情況下,方法 makeASandwich() 就會拋出一個錯誤咙咽。由于 makeASandwich() 的拋出老玛,方法的調(diào)用被包裹在了一個 try 的表達式中。通過將方法的調(diào)用包裹在 do 語句中钧敞,任何拋出來的錯誤都會被傳遞到預先提供的 catch 分句中蜡豹。
如果沒有錯誤拋出,方法 eatASandwich() 就會被調(diào)用溉苛,如果有錯誤拋出且滿足 Error.OutOfCleanDishes 這個條件镜廉,方法 washDishes() 就會被執(zhí)行。如果一個錯誤被拋出愚战,而它又滿足 Error.MissingIngredients 的條件娇唯,那么 buyGroceries(_:) 就會協(xié)同被 catch 模式捕獲的 String值一起調(diào)用。
斷言和先決條件
斷言和先決條件用來檢測運行時發(fā)生的事情寂玲。你可以使用它們來保證在執(zhí)行后續(xù)代碼前某必要條件是滿足的塔插。如果布爾條件在斷言或先決條件中計算為 true ,代碼就正常繼續(xù)執(zhí)行拓哟。如果條件計算為 false 想许,那么程序當前的狀態(tài)就是非法的;代碼執(zhí)行結(jié)束断序,然后你的 app 終止流纹。
斷言和先決條件的不同之處在于他們什么時候做檢查:斷言只在 debug 構(gòu)建的時候檢查,但先決條件則在 debug 和生產(chǎn)構(gòu)建中生效逢倍。在生產(chǎn)構(gòu)建中捧颅,斷言中的條件不會被計算。這就是說你可以在開發(fā)的過程當中隨便使用斷言而無需擔心影響生產(chǎn)性能较雕。
使用斷言進行調(diào)試
斷言會在運行的時候檢查一個邏輯條件是否為 true 碉哑。顧名思義,斷言可以“斷言”一個條件是否為真亮蒋。你可以使用斷言確保在運行其他代碼之前必要的條件已經(jīng)被滿足扣典。如果條件判斷為 true,代碼運行會繼續(xù)進行慎玖;如果條件判斷為 false贮尖,代碼運行結(jié)束,你的應用也就中止了趁怔。
如果你的代碼在調(diào)試環(huán)境下觸發(fā)了一個斷言湿硝,例如你在 Xcode 中創(chuàng)建并運行一個應用薪前,你可以明確的知道不可用的狀態(tài)發(fā)生在什么地方,還能檢查斷言被觸發(fā)時你的應用的狀態(tài)关斜。另外示括,斷言還允許你附加一條調(diào)試的信息。
你可以使用全局函數(shù) assert(::) 函數(shù)來寫斷言痢畜。向 assert(::) 函數(shù)傳入一個結(jié)果為 true 或者 false 的表達式以及一條會在結(jié)果為 false 的時候顯式的信息:
let age = -3
assert(age >= 0, "A person's age cannot be less than zero")
// this causes the assertion to trigger, because age is not >= 0
斷言信息可以刪掉如果你想的話垛膝,就像下邊的栗子:
assert(age >= 0)
如果代碼已經(jīng)檢查了條件,你可以使用 assertionFailure(_:file:line:) 函數(shù)來標明斷言失敗丁稀,比如:
if age > 10 {
print("You can ride the roller-coaster or the ferris wheel.")
} else if age > 0 {
print("You can ride the ferris wheel.")
} else {
assertionFailure("A person's age can't be less than zero.")
}
強制先決條件
在你代碼中任何條件可能潛在為假但必須肯定為真才能繼續(xù)執(zhí)行的地方使用先決條件吼拥。比如說,使用先決條件來檢測下標沒有越界线衫,或者檢測函數(shù)是否收到了一個合法的值凿可。
你可以通過調(diào)用 precondition(::file:line:) 函數(shù)來寫先決條件。給這個函數(shù)傳入表達式計算為 true 或 false 授账,如果條件的結(jié)果是 false 信息就會顯示出來矿酵。比如說:
// In the implementation of a subscript...
precondition(index > 0, "Index must be greater than zero.")
你可以調(diào)用 preconditionFailure(_:file:line:) 函數(shù)來標明錯誤發(fā)生了——比如說,如果 switch 的默認情況被選中矗积,但所有的合法輸入數(shù)據(jù)應該被其他 switch 的情況處理。
如果你在不檢查模式編譯( -Ounchecked )敞咧,先決條件不會檢查棘捣。編譯器假定先決條件永遠為真,并且它根據(jù)你的代碼進行優(yōu)化休建≌Э郑總之, fatalError(:file:line:) 函數(shù)一定會終止執(zhí)行测砂,無論你優(yōu)化設定如何茵烈。
你可以在草擬和早期開發(fā)過程中使用 fatalError(:file:line:) 函數(shù)標記那些還沒實現(xiàn)的功能,通過使用 fatalError("Unimplemented") 來作為代替砌些。由于致命錯誤永遠不會被優(yōu)化呜投,不同于斷言和先決條件,你可以確定執(zhí)行遇到這些臨時占位永遠會停止存璃。