Swift學習記錄

簡介

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í)行遇到這些臨時占位永遠會停止存璃。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仑荐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子纵东,更是在濱河造成了極大的恐慌粘招,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件偎球,死亡現(xiàn)場離奇詭異洒扎,居然都是意外死亡辑甜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門袍冷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來磷醋,“玉大人,你說我怎么就攤上這事难裆∽犹矗” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵乃戈,是天一觀的道長褂痰。 經(jīng)常有香客問我,道長症虑,這世上最難降的妖魔是什么缩歪? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮谍憔,結(jié)果婚禮上匪蝙,老公的妹妹穿的比我還像新娘。我一直安慰自己习贫,他們只是感情好逛球,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著苫昌,像睡著了一般颤绕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上祟身,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天奥务,我揣著相機與錄音,去河邊找鬼袜硫。 笑死氯葬,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的婉陷。 我是一名探鬼主播帚称,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼秽澳!你這毒婦竟也來了世杀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤肝集,失蹤者是張志新(化名)和其女友劉穎瞻坝,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡所刀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年衙荐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浮创。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡忧吟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出斩披,到底是詐尸還是另有隱情溜族,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布垦沉,位于F島的核電站煌抒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏厕倍。R本人自食惡果不足惜寡壮,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望讹弯。 院中可真熱鬧况既,春花似錦、人聲如沸组民。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽臭胜。三九已至降狠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間庇楞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工否纬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吕晌,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓临燃,卻偏偏與公主長得像睛驳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子膜廊,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容