版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/u010046908/article/details/51332496
1常量和變量
常量和變量把一個名字和一個指定類型的值關聯起來。常量的值一旦設定就不能改變,而變量的值可以随意更改。
1.1聲明常量和變量
常量和變量必須在使用前聲明,用 let 來聲明常量,用 var 來聲明變量。
let maximumNumberOfLoginAttempts = 10//允許的最大嘗試登入次數
var currentLoginAttempt = 0//目前嘗試登入次數
這兩行代碼可以被了解為:
聲明一個名字是 maximumNumberOfLoginAttempts 的新常量,并給它一個值 10 。然後,聲明一個名字是 currentLoginAttempt 的變量并将它的值初始化為 0 。在這個例子中,允許的最大嘗試登入次數被聲明為一個常量,因為這個值不會改變。目前嘗試登入次數被聲明為一個變量,因為每次嘗試登入失敗的時候都需要增加這個值。
你可以在一行中聲明多個常量或者多個變量,用逗号隔開:
var x = 1.0, y = 2.0, z = 3.0
var x = 12, y = 22, z = 32
1.2類型的标注
當你聲明常量或者變量的時候可以加上類型标注(type annotation),說明常量或者變量中要存儲的值的類
型。如果要添加類型标注,需要在常量或者變量名後面加上一個冒号和空格,然後加上類型名稱。
這個例子給 welcomeMessage 變量添加了類型标注,表示這個變量可以存儲 String 類型的值:
var welcomeMessage: String
**聲明中的冒号代表着“是…類型”,是以這行代碼可以被了解為:
“聲明一個類型為 String ,名字為 welcomeMessage 的變量。”
“類型為 String ”的意思是“可以存儲任意 String 類型的值。”
welcomeMessage 變量現在可以被設定成任意字元串:**
welcomeMessage = "Hello"
你可以在一行中定義多個同樣類型的變量,用逗号分割,并在最後一個變量名之後添加類型标注:
var red, green, blue: Double
注意:
一般來說你很少需要寫類型标注。如果你在聲明常量或者變量的時候賦了一個初始值,Swift可以推斷出這個常
量或者變量的類型。在上面的例子中,沒有給 welcomeMessage 賦初始
值,是以變量 welcomeMessage 的類型是通過一個類型标注指定的,而不是通過初始值推斷的。
1.3常量和變量的命名
你可以用任何你喜歡的字元作為常量和變量名,包括 Unicode 字元:
let π = 3.14159
let 你好 = "你好世界"
let ?? = "dogcow"
常量與變量名不能包含數學符号,箭頭,保留的(或者非法的)Unicode 碼位,連線與制表符。也不能以數字開
頭,但是可以在常量與變量名的其他地方包含數字。
一旦你将常量或者變量聲明為确定的類型,你就不能使用相同的名字再次進行聲明,或者改變其存儲的值的類
型。同時,你也不能将常量與變量進行互轉。
如果你需要使用與Swift保留關鍵字相同的名稱作為常量或者變量名,你可以使用反引号(`)将關鍵字包圍的方
式将其作為名字使用。無論如何,你應當避免使用關鍵字作為常量或變量名。
你可以更改現有的變量值為其他同類型的值,在下面的例子中, friendlyWelcome 的值從 “Hello!” 改為了 “Bonj
our!” :
var friendlyWelcome = "Hello!"
friendlyWelcome = "Bonjour!"
// friendlyWelcome 現在是 “Bonjour!”
與變量不同,常量的值一旦被确定就不能更改了。嘗試這樣做會導緻編譯時報錯:
let languageName = "Swift"
languageName = "Swift++"
// 這會報編譯時錯誤 - languageName 不可改變
1.4輸出常量和變量
你可以用 print(_:separator:terminator:) 函數來輸出目前常量或變量的值:
print(friendlyWelcome)
// 輸出 “Bonjour!”
print(_:separator:terminator:) 是一個用來輸出一個或多個值到适當輸出區的全局函數
**注意:**Swift 用字元串插值(string interpolation)的方式把常量名或者變量名當做占位符加入到長字元串中,Swift 會
用目前常量或變量的值替換這些占位符。将常量或變量名放入圓括号中,并在開括号前使用反斜杠将其轉義:
print("The current value of friendlyWelcome is \(friendlyWelcome)")
// 輸出 "The current value of friendlyWelcome is Bonjour!
2.注釋
2.1 單行注釋
Swift 中的注釋與C 語言的注釋非常相似。單行注釋以雙正斜杠( // )作為起始标記:
// 這是一個注釋
2.2 行多行注釋,
其起始标記為單個正斜杠後跟随一個星号( /* ),終止标記為一個星号後跟随單個正斜杠( */ ):
/* 這是一個,
多行注釋 */
2.3 Swift 的多行注釋可以嵌套在其它的多行注釋之中
/* 這是第一個多行注釋的開頭
/* 這是第二個被嵌套的多行注釋 */
這是第一個多行注釋的結尾 */
3 分号
Swift 并不強制要求你在每條語句的結尾處使用分号( ; ),當然,你也可以按照你自己的習慣添加分号。有一種情況下必須要用分号,即你打算在同一行内寫多條獨立的語句:
let cat = "?"; print(cat);var title :String;
// 輸出 "?"
4 整數
整數就是沒有小數部分的數字,比如 42 和 -23 。整數可以是 有符号 (正、負、零)或者 無符号 (正、零)。
Swift 提供了8,16,32和64位的有符号和無符号整數類型。這些整數類型和 C 語言的命名方式很像,比如8位
無符号整數類型是 UInt8 ,32位有符号整數類型是 Int32 。就像 Swift 的其他類型一樣,整數類型采用大寫命名
法。
4.1整數範圍
你可以通路不同整數類型的 min 和 max 屬性來擷取對應類型的最小值和最大值:
let minValue = UInt8.min // minValue 為 0,是 UInt8 類型
let maxValue = UInt8.max // maxValue 為 255,是 UInt8 類型
min 和 max 所傳回值的類型,正是其所對的整數類型(如上例UInt8, 所傳回的類型是UInt8),可用在表達式中
相同類型值旁。
4.2 Int
一般來說,你不需要專門指定整數的長度。Swift 提供了一個特殊的整數類型 Int ,長度與目前平台的原生字長相
同:
? 在32位平台上, Int 和 Int32 長度相同。
? 在64位平台上, Int 和 Int64 長度相同。
除非你需要特定長度的整數,一般來說使用 Int 就夠了。這可以提高代碼一緻性和可複用性。即使是在32位平台
上, Int 可以存儲的整數範圍也可以達到 -2,147,483,648 ~ 2,147,483,647 ,大多數時候這已經足夠大了。
4.3UInt
Swift 也提供了一個特殊的無符号類型 UInt ,長度與目前平台的原生字長相同:
? 在32位平台上, UInt 和 UInt32 長度相同。
? 在64位平台上, UInt 和 UInt64 長度相同。
盡量不要使用 UInt ,除非你真的需要存儲一個和目前平台原生字長相同的無符号整數。除了這種情況,最好使用 Int ,即使你要存儲的值已知是非負的。統一使用 Int 可以提高代碼的可複用性,避免不同類型數字之間的轉換,并且比對數字的類型推斷。
5.浮點數
浮點數是有小數部分的數字,比如 3.14159 , 0.1 和 -273.15 。
浮點類型比整數類型表示的範圍更大,可以存儲比 Int 類型更大或者更小的數字。Swift 提供了兩種有符号浮點數
類型:
? Double 表示64位浮點數。當你需要存儲很大或者很高精度的浮點數時請使用此類型。
? Float 表示32位浮點數。精度要求不高的話可以使用此類型。
注意:
Double 精确度很高,至少有15位數字,而 Float 最少隻有6位數字。選擇哪個類型取決于你的代碼需要處理的
值的範圍。
6.類型安全和類型推斷
Swift 是一個類型安全(type safe)的語言。類型安全的語言可以讓你清楚地知道代碼要處理的值的類型。如果你的代碼需要一個 String ,你絕對不可能不小心傳進去一個 Int 。由于 Swift 是類型安全的,是以它會在編譯你的代碼時進行類型檢查(type checks),并把不比對的類型标記
為錯誤。這可以讓你在開發的時候盡早發現并修複錯誤。
當你要處理不同類型的值時,類型檢查可以幫你避免錯誤。然而,這并不是說你每次聲明常量和變量的時候都需要顯式指定類型。如果你沒有顯式指定類型,Swift 會使用 類型推斷 (type inference)來選擇合适的類型。有了類型推斷,編譯器可以在編譯代碼的時候自動推斷出表達式的類型。原理很簡單,隻要檢查你賦的值即可。
因為有類型推斷,和 C 或者 Objective-C 比起來 Swift 很少需要聲明類型。常量和變量雖然需要明确類型,但是大部分工作并不需要你自己來完成。當你聲明常量或者變量并賦初值的時候類型推斷非常有用。當你在聲明常量或者變量的時候賦給它們一個字面量(literal value 或 literal)即可觸發類型推斷。(字面量就是會直接出現在你代碼中的值,比如 42 和 3.14159 。)
例如,如果你給一個新常量指派 42 并且沒有标明類型,Swift 可以推斷出常量類型是 Int ,因為你給它賦的初始
值看起來像一個整數:
let meaningOfLife = 42
// meaningOfLife 會被推測為 Int 類型
同理,如果你沒有給浮點字面量标明類型,Swift 會推斷你想要的是 Double :
let pi = 3.14159
// pi 會被推測為 Double 類型
當推斷浮點數的類型時,Swift 總是會選擇 Double 而不是 Float 。
如果表達式中同時出現了整數和浮點數,會被推斷為 Double 類型:
let anotherPi = 3 + 0.14159
// anotherPi 會被推測為 Double 類型
原始值 3 沒有顯式聲明類型,而表達式中出現了一個浮點字面量,是以表達式會被推斷為 Double 類型。
7.數值型字面量
整數字面量可以被寫作:
? 一個十進制數,沒有字首
? 一個二進制數,字首是 0b
? 一個八進制數,字首是 0o
? 一個十六進制數,字首是 0x
下面的所有整數字面量的十進制值都是 17 :
let decimalInteger = 17
let binaryInteger = 0b10001 // 二進制的17
let octalInteger = 0o21 // 八進制的17
let hexadecimalInteger = 0x11 // 十六進制的17
浮點字面量可以是十進制(沒有字首)或者是十六進制(字首是 0x )。小數點兩邊必須有至少一個十進制數
字(或者是十六進制的數字)。浮點字面量還有一個可選的指數(exponent,在十進制浮點數中通過大寫或者小
寫的 e 來指定,在十六進制浮點數中通過大寫或者小寫的 p 來指定。
如果一個十進制數的指數為 exp ,那這個數相當于基數和10^exp的乘積: * 1.25e2 表示 1.25 × 10^2,等于
125.0 。 * 1.25e-2 表示 1.25 × 10^-2,等于 0.0125 。
如果一個十六進制數的指數為 exp ,那這個數相當于基數和2^exp的乘積: * 0xFp2 表示 15 × 2^2,等于 6
0.0 。 * 0xFp-2 表示 15 × 2^-2,等于 3.75 。
下面的這些浮點字面量都等于十進制的 12.1875 :
let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0
數值類字面量可以包括額外的格式來增強可讀性。整數和浮點數都可以添加額外的零并且包含下劃線,并不會影
響字面量:
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1
8.數值型類型轉換
通常來講,即使代碼中的整數常量和變量已知非負,也請使用 Int 類型。總是使用預設的整數類型可以保證你的
整數常量和變量可以直接被複用并且可以比對整數類字面量的類型推斷。
隻有在必要的時候才使用其他整數類型,比如要處理外部的長度明确的資料或者為了優化性能、記憶體占用等
等。使用顯式指定長度的類型可以及時發現值溢出并且可以暗示正在處理特殊資料。
8.2整數轉換
不同整數類型的變量和常量可以存儲不同範圍的數字。 Int8 類型的常量或者變量可以存儲的數字範圍是 -12
8 ~ 127 ,而 UInt8 類型的常量或者變量能存儲的數字範圍是 0 ~ 255 。如果數字超出了常量或者變量可存儲的
範圍,編譯的時候會報錯:
let cannotBeNegative: UInt8 = -1
// UInt8 類型不能存儲負數,是以會報錯
let tooBig: Int8 = Int8.max + 1
// Int8 類型不能存儲超過最大值的數,是以會報錯
由于每種整數類型都可以存儲不同範圍的值,是以你必須根據不同情況選擇性使用數值型類型轉換。這種選擇性
使用的方式,可以預防隐式轉換的錯誤并讓你的代碼中的類型轉換意圖變得清晰。
要将一種數字類型轉換成另一種,你要用目前值來初始化一個期望類型的新數字,這個數字的類型就是你的目标
類型。在下面的例子中,常量 twoThousand 是 UInt16 類型,然而常量 one 是 UInt8 類型。它們不能直接相
加,因為它們類型不同。是以要調用 UInt16(one) 來建立一個新的 UInt16 數字并用 one 的值來初始化,然後使
用這個新數字來計算:
let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)
現在兩個數字的類型都是 UInt16 ,可以進行相加。目标常量 twoThousandAndOne 的類型被推斷為 UInt1
6 ,因為它是兩個 UInt16 值的和。
SomeType(ofInitialValue) 是調用 Swift 構造器并傳入一個初始值的預設方法。在語言内部, UInt16 有一個構
造器,可以接受一個 UInt8 類型的值,是以這個構造器可以用現有的 UInt8 來建立一個新的 UInt16 。注意,你
并不能傳入任意類型的值,隻能傳入 UInt16 内部有對應構造器的值。不過你可以擴充現有的類型來讓它可以接收
其他類型的值(包括自定義類型).
8.3整數和浮點數轉換
整數和浮點數的轉換必須顯式指定類型:
let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine
// pi 等于 3.14159,是以被推測為 Double 類型
這個例子中,常量 three 的值被用來建立一個 Double 類型的值,是以加号兩邊的數類型須相同。如果不進行轉
換,兩者無法相加。
浮點數到整數的反向轉換同樣行,整數類型可以用 Double 或者 Float 類型來初始化:
let integerPi = Int(pi)
// integerPi 等于 3,是以被推測為 Int 類型
當用這種方式來初始化一個新的整數值時,浮點值會被截斷。也就是說 4.75 會變成 4 , -3.9 會變成 -3 。
結合數字類常量和變量不同于結合數字類字面量。字面量 3 可以直接和字面量 0.14159 相加,因為數字字面量
本身沒有明确的類型。它們的類型隻在編譯器需要求值的時候被推測。
9類型别名
類型别名(type aliases)就是給現有類型定義另一個名字。你可以使用 typealias 關鍵字來定義類型别名。
當你想要給現有類型起一個更有意義的名字時,類型别名非常有用。假設你正在處理特定長度的外部資源的數
據:
typealias AudioSample = UInt16
定義了一個類型别名之後,你可以在任何使用原始名的地方使用别名:
var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound 現在是 0
本例中, AudioSample 被定義為 UInt16 的一個别名。因為它是别名, AudioSample.min 實際上是 UInt16.mi
n ,是以會給 maxAmplitudeFound 賦一個初值 0 。
10 布爾值(Bool)
Swift 有一個基本的布爾(Boolean)類型,叫做 Bool 。布爾值指邏輯上的值,因為它們隻能是真或者假。Swift 有兩個布爾常量, true 和 false :
let orangesAreOrange = true
let turnipsAreDelicious = false
orangesAreOrange 和 turnipsAreDelicious 的類型會被推斷為 Bool ,因為它們的初值是布爾字面量。就像之前提到的 Int 和 Double 一樣,如果你建立變量的時候給它們指派 true 或者 false ,那你不需要将常量或者變量聲明為 Bool 類型。初始化常量或者變量的時候如果所賦的值類型已知,就可以觸發類型推斷,這讓 Swift 代碼更加簡潔并且可讀性更高。當你編寫條件語句比如 if 語句的時候,布爾值非常有用:
if turnipsAreDelicious {
print("Mmm, tasty turnips!")
} else {
print("Eww, turnips are horrible.")
}
// 輸出 "Eww, turnips are horrible."
條件語句,例如 if
如果你在需要使用 Bool 類型的地方使用了非布爾值,Swift 的類型安全機制會報錯。下面的例子會報告一個編譯
時錯誤:
let i = 1
if i {
// 這個例子不會通過編譯,會報錯
}
然而,下面的例子是合法的:
let i = 1
if i == 1 {
// 這個例子會編譯成功
}
i == 1 的比較結果是 Bool 類型,是以第二個例子可以通過類型檢查。類似 i == 1 這樣的比較.和 Swift 中的其他類型安全的例子一樣,這個方法可以避免錯誤并保證這塊代碼的意圖總是清晰的。
11.元組
元組(tuples)把多個值組合成一個複合值。元組内的值可以是任意類型,并不要求是相同類型。
下面這個例子中, (404, “Not Found”) 是一個描述 HTTP 狀态碼(HTTP status code)的元組。HTTP 狀态
碼是當你請求網頁的時候 web 伺服器傳回的一個特殊值。如果你請求的網頁不存在就會傳回一個 404 Not Foun
d 狀态碼。
let http404Error = (404, "Not Found")
// http404Error 的類型是 (Int, String),值是 (404, "Not Found")
(404, “Not Found”) 元組把一個 Int 值和一個 String 值組合起來表示 HTTP 狀态碼的兩個部分:一個數字和一
個人類可讀的描述。這個元組可以被描述為“一個類型為 (Int, String) 的元組”。
你可以把任意順序的類型組合成一個元組,這個元組可以包含所有類型。隻要你想,你可以建立一個類型為 (Int, I
nt, Int) 或者 (String, Bool) 或者其他任何你想要的組合的元組。
你可以将一個元組的内容分解(decompose)成單獨的常量和變量,然後你就可以正常使用它們了:
let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)")
// 輸出 "The status code is 404"
print("The status message is \(statusMessage)")
// 輸出 "The status message is Not Found"
如果你隻需要一部分元組值,分解的時候可以把要忽略的部分用下劃線( _ )标記:
let (justTheStatusCode, _) = http404Error
print("The status code is \(justTheStatusCode)")
// 輸出 "The status code is 404"
此外,你還可以通過下标來通路元組中的單個元素,下标從零開始:
print("The status code is \(http404Error.0)")
// 輸出 "The status code is 404"
print("The status message is \(http404Error.1)")
// 輸出 "The status message is Not Found"
你可以在定義元組的時候給單個元素命名:
let http200Status = (statusCode: 200, description: “OK”)
給元組中的元素命名後,你可以通過名字來擷取這些元素的值:
print("The status code is \(http200Status.statusCode)")
// 輸出 "The status code is 200"
print("The status message is \(http200Status.description)")
// 輸出 "The status message is OK"
作為函數傳回值時,元組非常有用。一個用來擷取網頁的函數可能會傳回一個 (Int, String) 元組來描述是否擷取
成功。和隻能傳回一個類型的值比較起來,一個包含兩個不同類型值的元組可以讓函數的傳回資訊更有用。請參
考函數參數與傳回值 (頁 0)。
元組在臨時組織值的時候很有用,但是并不适合建立複雜的資料結構。如果你的資料結構并不是臨時使用,請使
用類或者結構體而不是元組。請參考類和結構體。
10.可選類型
10.1nil
你可以給可選變量指派為 nil 來表示它沒有值:
var serverResponseCode: Int? = 404
// serverResponseCode 包含一個可選的 Int 值 404
serverResponseCode = nil
// serverResponseCode 現在不包含值
nil 不能用于非可選的常量和變量。如果你的代碼中有常量或者變量需要處理值缺失的情況,請把它們聲明成對
應的可選類型。
如果你聲明一個可選常量或者變量但是沒有指派,它們會自動被設定為 nil :
var surveyAnswer: String?
// surveyAnswer 被自動設定為 nil
11.錯誤處理
你可以使用錯誤處理(error handling)來應對程式執行中可能會遇到的錯誤條件。
相對于可選中運用值的存在與缺失來表達函數的成功與失敗,錯誤處理可以推斷失敗的原因,并傳播至程式的其
他部分。
當一個函數遇到錯誤條件,它能報錯。調用函數的地方能抛出錯誤消息并合理處理。
func canThrowAnErrow() throws {
// 這個函數有可能抛出錯誤
}
一個函數可以通過在聲明中添加 throws 關鍵詞來抛出錯誤消息。當你的函數能抛出錯誤消息時, 你應該在表達式
中前置 try 關鍵詞。
do {
try canThrowAnErrow()
// 沒有錯誤消息抛出
} catch {
// 有一個錯誤消息抛出
}
一個 do 語句建立了一個新的包含作用域,使得錯誤能被傳播到一個或多個 catch 從句。
這裡有一個錯誤處理如何用來應對不同錯誤條件的例子。
func makeASandwich() throws {
// ...
}
do {
try makeASandwich()
eatASandwich()
} catch Error.OutOfCleanDishes {
washDishes()
} catch Error.MissingIngredients(let ingredients) {
buyGroceries(ingredients)
}
在此例中, makeASandwich() (做一個三明治)函數會抛出一個錯誤消息如果沒有幹淨的盤子或者某個原料缺
失。因為 makeASandwich() 抛出錯誤,函數調用被包裹在 try 表達式中。将函數包裹在一個 do 語句中,任何被
抛出的錯誤會被傳播到提供的 catch 從句中。
如果沒有錯誤被抛出, eatASandwich() 函數會被調用。如果一個比對 Error.OutOfCleanDishes 的錯誤被抛出, washDishes 函數會被調用。如果一個比對 Error.MissingIngredients 的錯誤被抛出,buyGroceries(_:) 函數會随着被 catch 所捕捉到的關聯值 [String] 被調用。抛出,捕捉,以及傳播錯誤會在錯誤處理。
學習位址