常量和變量
常量的值一旦設定就不能改變,而變量的值可以隨意更改。
1.1用let來聲明常量,必須在使用前聲明
let totle = 10 //聲明一個名字是totle的新常量,并給它一個值10
1.2用var來聲明變量
var currentPage = 0 //聲明一個名字是currentPage的變量并將它的值初始化為0
currentPage += 1//即可以修改變量的值
//你可以在一行中聲明多個常量或者多個變量,用逗號隔開:
var x = 0.0, y = 0.0, z = 0.0
注意:如果你的代碼中有不需要改變的值,請使用let關鍵字將它聲明為常量。只將需要改變的值聲明為變量。
類型標注
當你聲明常量或者變量的時候可以加上類型標注(type annotation),說明常量或者變量中要存儲的值的類型。如果要添加類型標注,需要在常量或者變量名后面加上一個冒號和空格,然后加上類型名稱。
1.1這個例子給welcomeMessage變量添加了類型標注,表示這個變量可以存儲String類型的值:
var welcomeMessage: String //聲明一個類型為String,名字為welcomeMessage的變量
welcomeMessage = "Hello" //welcomeMessage變量現在可以被設置成任意字符串
你也可以在聲明的時候賦初始值
let helloWord = "你好世界"
常量和變量的命名
你可以用任何你喜歡的字符作為常量和變量名,包括 Unicode 字符:
常量與變量名不能包含數學符號,箭頭,保留的(或者非法的)Unicode 碼位,連線與制表符。也不能以數字開頭,但是可以在常量與變量名的其他地方包含數字。
let π = 3.14159
let 你好 = "你好世界"
let ???????? = "dogcow"
注意:如果你需要使用與Swift保留關鍵字相同的名稱作為常量或者變量名,你可以使用反引號(`)將關鍵字包圍的方式將其作為名字使用。無論如何,你應當避免使用關鍵字作為常量或變量名,除非你別無選擇。
輸出常量和變量
你可以用println函數來輸出當前常量或變量的值:
println(welcomeMessage) //println是一個用來輸出的全局函數,輸出的內容會在最后換行。
與 Cocoa 里的NSLog函數類似的是,println函數可以輸出更復雜的信息。這些信息可以包含當前常量和變量的值。
Swift 用字符串插值(string interpolation)的方式把常量名或者變量名當做占位符加入到長字符串中,Swift 會用當前常量或變量的值替換這些占位符。將常量或變量名放入圓括號中,并在開括號前使用反斜杠將其轉義:
println("The current value of friendlyWelcome is \(welcomeMessage)")
// 輸出 "The current value of friendlyWelcome is Hello!
整數
整數就是沒有小數部分的數字,比如42和-23。整數可以是有符號(正、負、零)或者無符號(正、零)。
Swift 提供了8,16,32和64位的有符號和無符號整數類型。比如8位無符號整數類型是UInt8,32位有符號整數類型是Int32。就像 Swift 的其他類型一樣,整數類型采用大寫命名法。
1.1整數范圍
let minValue = UInt8.min // minValue 為 0,是 UInt8 類型的最小值
let maxValue = UInt8.max // maxValue 為 255,是 UInt8 類型的最大值
Int:
一般來說,你不需要專門指定整數的長度。Swift 提供了一個特殊的整數類型Int,長度與當前平臺的原生字長相同:
- 在32位平臺上,Int和Int32長度相同。
- 在64位平臺上,Int和Int64長度相同。
UInt:
Swift 也提供了一個特殊的無符號類型UInt,長度與當前平臺的原生字長相
同:
- 在32位平臺上,UInt和UInt32長度相同。
- 在64位平臺上,UInt和UInt64長度相同。
浮點數:
浮點數是有小數部分的數字,比如3.14159,0.1和-273.15。
浮點類型比整數類型表示的范圍更大,可以存儲比Int類型更大或者更小的數字。Swift 提供了兩種有符號浮點數類型:
- Double表示64位浮點數。當你需要存儲很大或者很高精度的浮點數時請使用此類型。
- Float表示32位浮點數。精度要求不高的話可以使用此類型。
注意:Double精確度很高,至少有15位數字,而Float最少只有6位數字。選擇哪個類型取決于你的代碼需要處理的值的范圍。
數值型字面量
下面的所有整數字面量的十進制值都是17:
let decimalInteger = 17
let binaryInteger = 0b10001 // 二進制的17
let octalInteger = 0o21 // 八進制的17
let hexadecimalInteger = 0x11 // 十六進制的17
數值類字面量可以包括額外的格式來增強可讀性。整數和浮點數都可以添加額外的零并且包含下劃線,并不會影響字面量:
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1
數值型類型轉換
整數轉換
不同整數類型的變量和常量可以存儲不同范圍的數字。Int8類型的常量或者變量可以存儲的數字范圍是-128127,而UInt8類型的常量或者變量能存儲的數字范圍是0255。如果數字超出了常量或者變量可存儲的范圍,編譯的時候會報錯:
let cannotBeNegative: UInt8 = -1
// UInt8 類型不能存儲負數,所以會報錯
let tooBig: Int8 = Int8.max + 1
// Int8 類型不能存儲超過最大值的數,所以會報錯
現在兩個數字的類型都是UInt16,可以進行相加。目標常量twoThousandAndOne的類型被推測為UInt16,因為它是兩個UInt16值的和。
let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)
整數和浮點數轉換
整數和浮點數的轉換必須顯式指定類型:
常量three的值被用來創建一個Double類型的值,所以加號兩邊的數類型相同。如果不進行轉換,兩者無法相加。
let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi 等于 3.14159,所以被推測為 Double 類型
浮點數到整數的反向轉換同樣行,整數類型可以用Double或者Float類型來初始化:(相當于浮點數取整)
let integerPi = Int(pi)
// integerPi 等于 3,所以被推測為 Int 類型
類型別名
類型別名(type aliases)就是給現有類型定義另一個名字。你可以使用typealias關鍵字來定義類型別名。
typealias AudioSample = UInt16
//定義了一個類型別名之后,你可以在任何使用原始名的地方使用別名:
var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound 現在是 0
//AudioSample被定義為UInt16的一個別名。因為它是別名,AudioSample.min實際上是UInt16.min,所以會給maxAmplitudeFound賦一個初值0。
布爾值
Swift 有一個基本的布爾(Boolean)類型,叫做Bool。布爾值指邏輯上的(logical),因為它們只能是真或者假。
//Swift 有兩個布爾常量,true和false:
let orangesAreOrange = true
let turnipsAreDelicious = false
注意:如果你創建變量的時候給它們賦值true或者false,那你不需要將常量或者變量聲明為Bool類型。初始化常量或者變量的時候如果所賦的值類型已知,就可以觸發類型推測,這讓 Swift 代碼更加簡潔并且可讀性更高。
元組
元組(tuples)把多個值組合成一個復合值。元組內的值可以使任意類型,并不要求是相同類型。
//(404, "Not Found")元組把一個Int值和一個String值組合起來表示 HTTP 狀態碼的兩個部分:
//一個數字和一個人類可讀的描述。這個元組可以被描述為“一個類型為(Int, String)的元組”。
let http404Error = (404, "Not Found")
// http404Error 的類型是 (Int, String),值是 (404, "Not Found")
你可以把任意順序的類型組合成一個元組,這個元組可以包含所有類型。只要你想,你可以創建一個類型為(Int, Int, Int)或者(String, Bool)或者其他任何你想要的組合的元組。
你可以將一個元組的內容分解(decompose)成單獨的常量和變量,然后你就可以正常使用它們了:
let (statusCode, statusMessage) = http404Error
println("The status code is \(statusCode)")
// 輸出 "The status code is 404"
println("The status message is \(statusMessage)")
// 輸出 "The status message is Not Found"
如果你只需要一部分元組值,分解的時候可以把要忽略的部分用下劃線(_)標記:
let (justTheStatusCode, _) = http404Error
println("The status code is \(justTheStatusCode)")
// 輸出 "The status code is 404"
你還可以通過下標來訪問元組中的單個元素,下標從零開始:
println("The status code is \(http404Error.0)")
// 輸出 "The status code is 404"
println("The status message is \(http404Error.1)")
// 輸出 "The status message is Not Found"
可以在定義元組的時候給單個元素命名:
let http200Status = (statusCode: 200, description: "OK")
給元組中的元素命名后,你可以通過名字來獲取這些元素的值:
println("The status code is \(http200Status.statusCode)")
// 輸出 "The status code is 200"
println("The status message is \(http200Status.description)")
// 輸出 "The status message is OK"
注意:作為函數返回值時,元組非常有用。和只能返回一個類型的值比較起來,一個包含兩個不同類型值的元組可以讓函數的返回信息更有用。元組在臨時組織值的時候很有用,但是并不適合創建復雜的數據結構。如果你的數據結構并不是臨時使用,請使用類或者結構體而不是元組。
可選
使用可選(optionals)來處理值可能缺失的情況。可選表示
注意:最接近的是 Objective-C 中的一個特性,一個方法要不返回一個對象要不返回nil,nil表示“缺少一個合法的對象”。然而,這只對對象起作用——對于結構體,基本的 C 類型或者枚舉類型不起作用。對于這些類型,Objective-C 方法一般會返回一個特殊值(比如NSNotFound)來暗示值缺失。這種方法假設方法的調用者知道并記得對特殊值進行判斷。然而,Swift 的可選可以讓你暗示任意類型的值缺失,并不需要一個特殊值。
let numberStr = "123"
let number:Int? = Int(numberStr)
//因為Int(numberStr)方法可能會失敗,所以它返回一個可選的(optional)Int,
//而不是一個Int。一個可選的Int被寫作Int?而不是Int。問號暗示包含的值是可選,
//也就是說可能包含Int值也可能不包含值。(不能包含其他任何值比如Bool值或者String值。只能是Int或者什么都沒有。)
if 語句以及強制解析
你可以使用if語句來判斷一個可選是否包含值。如果可選有值,結果是true;如果沒有值,結果是false。
當你確定可選包確實含值之后,你可以在可選的名字后面加一個感嘆號(!)來獲取值。這個驚嘆號表示“我知道這個可選有值,請使用它?!边@被稱為可選值的強制解析(forced unwrapping):
let numberStr:String? = nil
if (numberStr != nil) {
print(numberStr!)//如果存在 ,才強制解包
}else{
print("nil")
}
注意:使用!來獲取一個不存在的可選值會導致運行時錯誤。使用!來強制解析值之前,一定要確定可選包含一個非nil的值。
可選綁定
使用可選綁定(optional binding)來判斷可選是否包含值,如果包含就把值賦給一個臨時常量或者變量。可選綁定可以用在if和while語句中來對可選的值進行判斷并把值賦給一個常量或者變量。
let actualNumberStr:String = "qwe2"
if let actualNumber = Int(actualNumberStr){
print(actualNumber)
} else {
print("nil")
}
nil
你可以給可選變量賦值為nil來表示它沒有值:
var serverResponseCode: Int? = 404
// serverResponseCode 包含一個可選的 Int 值 404
serverResponseCode = nil
// serverResponseCode 現在不包含值
//如果你聲明一個可選常量或者變量但是沒有賦值,它們會自動被設置為nil:
var surveyAnswer: String? // surveyAnswer 被自動設置為 nil
注意1:nil不能用于非可選的常量和變量。如果你的代碼中有常量或者變量需要處理值缺失的情況,請把它們聲明成對應的可選類型。
注意2:Swift 的nil和 Objective-C 中的nil并不一樣。在 Objective-C 中,nil是一個指向不存在對象的指針。在 Swift 中,nil不是指針——它是一個確定的值,用來表示值缺失。任何類型的可選都可以被設置為nil,不只是對象類型。
隱式解析可選
可選暗示了常量或者變量可以“沒有值”??蛇x可以通過if語句來判斷是否有值,如果有值的話可以通過可選綁定來解析值。
類型的可選被定義為隱式解析可選(implicitly unwrapped optionals)。把想要用作可選的類型的后面的問號(String?)改成感嘆號(String!)來聲明一個隱式解析可選。
//一個隱式解析可選其實就是一個普通的可選,但是可以被當做非可選來使用,
//并不需要每次都使用解析來獲取可選值。
let possibleString: String? = "An optional string."
println(possibleString!) // 需要驚嘆號來獲取值
// 輸出 "An optional string."
let assumedString: String! = "An implicitly unwrapped optional string."
println(assumedString) // 不需要感嘆號
// 輸出 "An implicitly unwrapped optional string."
注意:如果你在隱式解析可選沒有值的時候嘗試取值,會觸發運行時錯誤。和你在沒有值的普通可選后面加一個驚嘆號一樣。
可以把隱式解析可選當做普通可選來判斷它是否包含值:
if assumedString {
println(assumedString)
}
// 輸出 "An implicitly unwrapped optional string."
可以在可選綁定中使用隱式解析可選來檢查并解析它的值:
if let definiteString = assumedString {
println(definiteString)
}
// 輸出 "An implicitly unwrapped optional string."
注意:如果一個變量之后可能變成nil的話請不要使用隱式解析可選。如果你需要在變量的生命周期中判斷是否是nil的話,請使用普通可選類型。
斷言
可選可以讓你判斷值是否存在,你可以在代碼中優雅地處理值缺失的情況。然而,在某些情況下,如果值缺失或者值并不滿足特定的條件,你的代碼可能并不需要繼續執行。這時,你可以在你的代碼中觸發一個斷言(assertion)來結束代碼運行并通過調試來找到值缺失的原因。
使用斷言進行調試
斷言會在運行時判斷一個邏輯條件是否為true。從字面意思來說,斷言“斷言”一個條件是否為真。你可以使用斷言來保證在運行其他代碼之前,某些重要的條件已經被滿足。如果條件判斷為true,代碼運行會繼續進行;如果條件判斷為false,代碼運行停止,你的應用被終止。
使用全局assert函數來寫一個斷言。向assert函數傳入一個結果為true或者false的表達式以及一條信息,當表達式為false的時候這條信息會被顯示:
let age = -3
assert(age >= 0, "A person's age cannot be less than zero")
// 因為 age < 0,所以斷言會觸發
何時使用斷言
當條件可能為假時使用斷言,但是最終一定要保證條件為真,這樣你的代碼才能繼續運行。
斷言的適用情景:
整數的附屬腳本索引被傳入一個自定義附屬腳本實現,但是下標索引值可能太小或者太大。
需要給函數傳入一個值,但是非法的值可能導致函數不能正常執行。
一個可選值現在是nil,但是后面的代碼運行需要一個非nil值。
注意:斷言可能導致你的應用終止運行,所以你應當仔細設計你的代碼來讓非法條件不會出現。然而,在你的應用發布之前,有時候非法條件可能出現,這時使用斷言可以快速發現問題。