Swift是一門新的開發語言,它能夠在iOS、macOS watchOS以及tvOS系統環境下進行應用的開發。html
Swift提供了它本身的C
和Objective-C
語言的全部基本數據類型。包括用於描述整數的Int,描述浮點型的Double
和Float
,描述布爾值的Bool
以及描述文本數據的String
。Swift也提供了三個主要的集合類型。好比集合類型中描述的的數組、集合、和字典。c++
和C語言同樣,Swift用變量來存儲和引用一個已經被聲明過名字的值。Swift一樣可以使用不可變數據類型的值。這些不能改變的值被稱爲常量,它比C語言中的常量更增強大。當你在使用不可變的值的時候,常量可以使你的代碼變得安全整潔。git
除了一些熟悉的類型以外,Swift還提供了Objective-C
沒有的高級類型,好比說:元組。元組可以讓你創建立和傳遞一組數據。函數中返回多個值的時候你能夠用元組做爲單個複合值來接收。github
Swift也提供了一些可選類型,它可以處理值缺失的狀況。可選值的意思是說:這裏有一個值,它等於X
或者它沒有值
。使用可選類型的以後就像使用Objective-C
中的空指針同樣,可是它的使用不只僅侷限於類,能夠是任意類型。和Objective-C
中的空指針相比來講,可選類型可不只僅是安全和更具表現力那麼簡單,它們是Swift最強大功能中的核心。web
Swift是一門安全類型的語言。這意味着這門語言能夠幫你弄明白你所使用的值是什麼類型的。若是你的代碼中須要的是String
,當你用Int
來給它賦值的時候,類型安全會阻止你這麼作。一樣的,若是你意外的將可選字符串傳遞給非可選字符串那麼類型安全會阻止你這麼作。類型安全能夠幫你在開發過程當中儘早的捕獲和修正錯誤。編程
常量和變量都須要用一個別名(好比說maximumNumberOfLoginAttempts
或者welcomeMessage
)以及一個特殊的數據類型的值(好比說數字10
和字符串hello
)來來進行關聯.常量的值一旦被初始化設置了以後就不能發生改變了,而變量則能夠在將來給它賦不一樣的值。swift
常量和變量在使用以前都是要通過聲明的。你能夠用關鍵詞let
來修飾一個常量,用var
關鍵詞來修飾一個變量。下面的例子是經過對常量和變量的使用來模擬一個用戶嘗試登陸次數的場景。數組
let maximumNumberOfLoginAttempts = 10 var currentLoginAttempts = 0
這段代碼能夠被解讀爲:
聲明一個新的名字爲maximumNumberOfLoginAttempts
的常量,它的值爲10。而後聲明一個新的名爲currentLoginAttempts
的變量,它的初始值爲0.
在這個例子中,最大容許嘗試登陸次數被聲明爲一個常量,由於最大的嘗試登陸次數不能被修改。當前的嘗試登陸次數被聲明爲一個變量,由於這個次值會隨着嘗試登陸失敗的次數的增長而增長。
你能夠連續聲明幾個常量或者變量在同一行中,他們之間用逗號隔開。xcode
var x = 0.0,y = 0.0,z = 0.0
注意:
若是你的代碼中使用的值是不會發生改變的那麼用let
關鍵字來聲明。若是聲明的值是須要發生改變的那麼用var
關鍵字來聲明。安全
在聲明常量和變量的時候你能夠爲它提供一個類型標註,它能夠很清楚的告訴編輯器常量和變量以什麼樣的數據類型被存儲。在常量和變量添加類型標註的時候在命名以後加一個冒號以以及空格,而後加上類型的名稱。
下面的這個例子裏給出一個叫作welcomeMessage
變量的類型標註,它代表了這個變量被存儲爲一個String
類型的值。
var welcomeMessage: String
在聲明的時候冒號的意思是「...類型的」,所以上面的代碼能夠這樣來理解:
聲明一個類型爲String
的變量welcomeMessage
。
類型字符串的意思是能夠存儲任意值的字符串,能夠把它理解爲有存儲功能的"事物類型"。
變量welcomeMessage
能夠被賦值爲任意的字符串而不報錯。
welcomeMessage = "Hello"
你能夠在一行定義多個同一種類型的變量,用逗號隔開在最後一個變量後面添加冒號和類型標註。
var red,green,blue:Double
注意:
在實際開發中咱們不多須要給常量/變量來寫類型標註,若是在定義常量/變量的時候給了一個初始值,那麼Swift能夠幫咱們推斷出常量/變量的類型。具體請參考類型和安全判斷
。在上面定義的變量welcomeMessage
中,咱們沒有給它賦初值,所以變量welcomeMessage
的類型是從類型標註裏判斷的,而不是從它初始值判斷的。
常量和變量的名字能夠包含任意字符串,固然也包括了Unicode
字符。
let π = 3.14159 let 你好 = "你好世界" let 🐶🐂 = "dogcow"
常量和變量的命名不能包含空格字符,數學符號,箭頭,保留的(或者非法的)Unicode碼位,連線與製表符。也不可以用數字開頭,儘管數字可能在名稱的其餘地方可使用。
一旦你爲常量和變量聲明一個肯定的類型以後,你不可以再聲明一個相同名字類型的常量/變量,而且也不可以改變它所存儲的類型,固然你也不可以對常量和變量的互換操做。
注意:
若是你須要使用和Swift保留關鍵字相同的名稱做爲常量和變量名。你可使用關鍵字反引號(`)將關鍵字包起來做爲它的名字,不到萬不得已的時候,建議你不要使用關鍵字來做爲常量和變量的名字。
你能夠改變一個變量的值爲另一種相同類型的值,在下面的例子中,friendWelcome
的值從hello!
變爲Bonjour!
。
var friendWelcome = "hello !" friendWelcome = "Bonjour !" // friendWelcome is now "Bonjour!"
和變量不一樣的是常量在初始化設置之後就不可以發生改變了。當你改變常量值的時候,編譯器會報錯。
let languageName = "Swift" languageName = "c++" //Cannot assign to value: 'languageName' is a 'let' constant // 這裏是一個編譯錯誤,languageName 不可以被改變.
你能夠用print(_:separator:terminator:)
這個函數打印出常量和變量的當前值。
print(friendWelcome) // 打印出 friendWelcome 的值
print(_:separator:terminator:)
函數是一個在全局的指定區域打印出一個甚至更多值的的函數。例如在Xcode裏面,print(_:separator:terminator:)
是在xcode的控制檯輸出的。separator
和terminator
參數都有默認值,所以你當你調用函數的時候能夠省略掉它們。函數默認經過換行符來結束當前行。若是不想換行,能夠默認添加一個空的字符串來代替,例如:print(someValue, terminator: "").
若是想了解更多關於參數的信息,能夠查看默認參數。
Swift用字符串插值的方式把常量名和變量名當作佔位符加入到長字符串中,Swift會把常量和變量的值替換掉這些佔位符。把常量和變量名放到括號裏面,並在括號前面加上反斜槓來轉義。
print("The currenct value of firendlyWelcome is \(friendWelcome)") // 打印出當前firendlyWelcome的值
注意:
字符串插值全部能用的選項在這裏能找到。
把你代碼裏不用執行的文本用打上註釋做爲註解或者一個標記來提醒你本身。在swift中,編譯器會忽略掉註釋的編譯。
在swift中註釋和在c語言的註釋十分類似。單行的註釋用//
來表示。
// This is a comment.
多行註釋以/*
開始,以*/
結尾。
/* This is also a comment. but is written over multiple lines. */
和C語言中多行註釋不一樣的是,swift中多行註釋是能夠進行嵌套的。你能夠寫一個嵌套的多行註釋用/*
開始 ,而後添加第二個多行註釋以/*
開始以*/
結束。最後用*/
來結束第一個多行註釋。
/* This is the start of the first multiline comment. /* This is the second,nested multiline comment. */ This is the end of the first mulitiline comment.*/
註釋的多行嵌套使得你在註釋大量代碼塊的時候更加便捷和容易,即便代碼裏已經存在多行註釋也沒有影響。
和其餘編程語言不一樣的是,在swift中,在代碼的結尾,不須要你寫分號(;)固然,你也能夠按照你的習慣來添加分號。有一種狀況是必需要添加分號的,那就是在一行中執行多個語句
let cat = "🐱";print(cat) // print "🐱"
整數就是沒有小數的數字,好比說:42和-23.整數能夠是有符號的類型(正數,負數和0),也能夠是無符號的類型(正數和0)。
swift
爲咱們提供了8位,16位,32位,以及64位的無符號和有符號的整數。這些整數的命名規則和c語言相似。好比說:有無符號的8位整數UInt8
和有符號的32位整數Int32
。像swift
中的其餘類型同樣,整數類的命名都是大寫字母開頭。
你能夠經過訪問整數的最大值屬性和最小值屬性在肯定他們的範圍。
let minValue = UInt8.min // UInt8的最小值爲0 let maxValue = UInt8.max // UInt8的最大值爲2 print("minValue of UInt8 is \(minValue) and maxValue of UInt8 is \(maxValue)。")
這些屬性的值代表了這種類型數據只能在規定範圍內進行操做(就像上面UInt8
的例子),所以同種類型的數據能夠在表達式中一塊兒使用。
在大多數狀況下,在寫代碼的過程當中咱們並不須要指定一個長度給Integer
。Swift
提供了另一個整數類型的數據Int
,它的長度和原平生臺的字節數相同。
Int
的長度和Int32
一致。Int
的長度和Int64
一致。若是你不須要爲整型添加特殊的長度處理,用默認的Int
來實現代碼就行。這能夠提升代碼的一致性和可複用性。甚至是在32位的平臺上,他可以儲存在-2
,147
,483
,648
和2
,147
,483
,647
範圍之間的數據,在不少時候這個範圍內的數據已經很大了。
swift
也爲咱們提供了無符號類型的整型數據。UInt
和原平生臺有着相同長度的字節數。
UInt
的長度和UInt32
一致。UInt
的長度和UInt64
一致。注意:
儘可能不要使用UInt
,除非你真的須要存儲一個和當前原平生臺長度相同的字節數的無符號整數時候,若是不是這種狀況,建議你最好使用Int
,即便你要存儲的對象已知是非負的。統一使用Int
提升了代碼的一致性和可複用性。避免在不一樣的數據類型進行轉換,而且匹配數字的類型進行判斷,具體請參考類型安全和類型推斷。
所謂浮點型數據就是帶有小數部分的數據。好比:3.14258
,0.1
和-273.15
。
浮點型所表明值得範圍要比整型要更大,它可以儲存比整型更小或者更大的值。Swift提供了兩種有符號的浮點數類型。
Double
類型表明的64位浮點型數據。Float
類型表明的32位浮點型數據。注意:Double
類型精度至少爲小數點後15位,Float
類型的精確度僅僅是小數點後6位。
你能夠根據本身編程的須要值的範圍選擇是Double
類型仍是Float
類型,若是兩種條件都知足,優先選擇Double
。
Swift是一個類型安全的語言,類型安全的語言可讓你清楚的知道你所處理的代碼值的類型。若是你代碼中須要的是String
,那麼。你若是給它賦值爲Int
類型的數據,那麼編譯器就會報錯。
由於Swift
是類型安全的語言,因此它在編譯的時候會對代碼進行類型的檢查。這在開發過程當中可以幫助你儘量早的發現和解決問題。
當你在處理不一樣類型數據的時候,類型檢查可以幫助避免一些問題。然而,這並不意味着你在每次聲明常量或者變量的時候都須要顯示指定類型。若是你沒有指定顯示類型,那麼swift會使用類型判斷來爲你選擇合適的類型。類型判斷確保了編譯器在編譯代碼的時候經過檢查你賦的值自動推斷出表達式的類型。
由於有了類型判斷,和c或者c++相比來講,swift不多須要你進行類型聲明。常量和變量雖然須要來明確類型,可是大部分工做並不須要你來完成,編譯器已經爲你完成了。
當你聲明一個常量或者變量賦初值的時候類型判斷變很是有用。在你聲明常量或者變量的時候,賦給它們一個字面量(literal value
或者literal
)就可以讓編譯器本身來進行類型判斷。(所謂字面量就是直接出如今代碼中的值,好比下面例子中的42
和3.14159
。)
例如:若是你給一個新的常量用字面量的形式給它賦值爲42
沒有聲明它的數據類型,Swift能推斷出你要給常量賦一個Int
類型的數據,由於你在初始化的時候給它賦值了一個像整型的數字。
let meaningOfLife = 42 // meaningOfLife will be inferred to be of type Int 這裏常量meaningOfLife 會被便以及推斷爲一個整型
同理,若是你沒有給浮點類型的數據標記類型,那麼Swift
會默認類型的Double
let pi = 3.14159 // pi will be inferred to be of type Double 這裏常量pi會被默認推斷爲DoubleL類型的數據。
當swift在推斷浮點型數據的時候,它會默認推斷爲Double
類型而不是Float
類型。
若是你在一個表達式中用整型和浮點型混合計算的時候,在上下文中會被swift
推斷爲Double
類型。
let anotherPi = 3 + 0.14159 // anotherPi will be inferred of type Double 這裏常量anotherPi會被swift推斷爲Double類型的數據。
初始值3沒有給顯式聲明類型,而且在表達式中出現了一個浮點類型的字面量,因此表達式被推斷爲Double
類型。
整數類型的字面量能夠被寫做:
0b
0o
0X
下面全部的整數型字面量都是表明十進制的值17
let decimalInteger = 17 let binaryInteger = 0b10001// 二進制的17 2*2*2*2+1 let octalInteger = 0o21 // 八進制的17 2*8+1*1 let hexadecimalInteger = 0x11 // 十六進制的17 16*1+1
浮點型的字面量能夠是十進制(沒有前綴),也能夠是十六進制的(帶有前綴)。在小數的兩遍必須是十進制的值值(或者十六進制有前綴的值)。十進制的浮點數能夠有一個可選的指數(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
或者60.0
。0xFp-2
表示的是15*2^-2
或者3.75
。
下面的浮點型的字面量都等價於十進制的值12.1875
。
//浮點類型的十進制的12.1875 let decimalDouble = 12.1875 let exponentDouble = 1.21875e1 let hexadecimalDouble = 0xC.3p0 //計算方式:0x表明16進制C表明12後面.3表明小數 因此整數部分應該是應該是12*(16^0)+0.3*(16^-1) 後面的p表明指數,以2爲底。因此完整表達式爲(12*(16^0)+0.3*(16^-1))*(2^0)
數字類型的字面量添加額外的標記可以使它們看起來更容易閱讀。整數和浮點型均可以添加額外的零加上下劃線來加強可閱讀性,而且不會影響字面量的值。
let paddedDouble = 000123.456 let oneMillion = 1_000_000 let justOverOneMillion = 1_000_000.000_000_000_1
即便常量和變量你已經知道它們是非負的,你也能夠在代碼中用Int
類型來修飾它們。使用默認整數數據類型保證了常量和變量能夠被複用而且能用來匹配整數字面量的類型推斷。
當咱們作特殊的任務時候纔會對整型類型作類型指定,好比:須要處理的外部的長度明確了數據或者爲了性能優化、內存佔用等等。使用顯式指定長度的類型能夠及時的發現值的溢出而且還能標記咱們在處理的是特殊的數據。
不一樣類型的整數能夠保存不一樣範圍的常量和變量。Int8類型的整數能夠存儲數據的範圍是-128
到127
。無符號整型的能夠存儲常量和變量的範圍是0
到255
。若是數字超出了常量和變量對應值的範圍,編譯的時候會報錯。
let cannotBeNegative:UInt8 = -1 //不在UInt8值範圍內報錯 let tooBig:Int8 = Int8.max + 1 //超出Int8值範圍內報錯
由於不一樣數據類型可以存儲數據的範圍是不同的,在進行類型轉換的時候你必須選擇一個合適的數據類型進行轉換。這種轉換方式可以讓你的代碼的意圖更明顯,而且可以防止你在隱式轉換中遇到的錯誤。
在轉換一個特殊的數字類型到另外一個類型的時候,你須要從新初始化一個你須要的目標數據。在下面的例子中,常量twoThousand
是一個UInt16
類型的數據,和它一塊兒須要轉換的數據類型是UInt8
,它們兩個不可以直接相加,由於他們兩個類型不同。
咱們能夠用UInt16(one)
來建立一個UInt
類型的數據用one
的值進行初始化。用初始化的數據類代替原始數據。
let twoThousand:UInt16 = 2_000 let one:UInt8 = 1 let twoThousandAndOne = twoThousand + UInt16(one)
由於等式兩邊的類型都是UInt16
,因此二者等式操做是被容許的。輸出的常量(twoThousandAndOne)
的數據類型被swift
推斷爲UInt16
,由於它是兩個UInt16的常量相加而來的。
SomeType(ofInitialValue)
調用的是swift
構造器並傳入一個初始值的默認方法。在語言的內部,UInt16有一個構造器能夠接收一個UInt8
類型的數據。這個構造的做用是經過已經存在的UInt8
類型的數據初始化一個UInt16
類型的數據。須要注意的是:你並不能任意的傳入值,只有在傳入UInt16
內部有對應構造器的值。不過你能夠擴展示有的類型,讓它來接收其餘類型的值(包括自定義的類型),具體請參考擴展。
在進行整數和浮點數類型轉換的時候必定要指定類型。
let three = 3 let pointOneFourOneFiveNine = 0.14159 let pi = Double(three) + pointOneFourOneFiveNine // pi等於3.14159,被Swift推斷爲double類型
在這裏,常量three
被當作一個Double
類型的數據來建立,所以+
兩邊應爲相同的類型。若是這裏沒有進行轉化,那麼+
(加號運算符)是不被容許使用的。
浮點型的數據和整型同樣能夠互相轉換。整型可使用Double
和Float
進行初始化。
let integerPi = Int(pi) //這裏integerPi等於3,被Swift推斷爲Int類型。
上面咱們使用浮點型數據進行初始化一個整型數據的時候,咱們發現浮點值被截斷了。這意味着4.75變成了4,-3.9被截斷爲-3。
注意:
結合數字型的常量和變量的規則和數字字面量的規則是不一樣的,在字面量3能夠和直接和字面量0.14159相加,由於數字型的字面量他們自己值是沒有特定類型的。它們的類型只有在編譯須要計算值的時候纔會被推斷。
類型別名是給已經存在的一個數據類型添加一個可選的名字。你能夠用關鍵字typealias
來定義這是一個類型別名。
當你想給現有的類型添加一個有意義的名字的時候,類型別名顯得特別的有用。咱們假設你正在處理特定長度的外部資源的數據的時候:
typealias AudioSample = UInt16
當你定義過一個類型別名的時候,你能夠在任意一個地方像使用原始名同樣來使用這個別名。
var maxAmplitudeFound = AudioSample.min // maxAmplitudeFound 如今的值是0
在這裏,AudioSample
被定義成一個值爲UInt16
的別名。正由於這是一個別名,因此咱們調用AudioSample.min
實際上就是調用UInt16.min
這個函數,這樣爲變量maxAmplitudeFound
提供了一個初始值0
。
Swift
有一個基礎的布爾類型叫作Bool
,布爾的值是邏輯上的值,所以只有真和假。Swift
爲咱們提供了兩個bool常量true
和false
。
let ornagesAndOrange = true let turnipsAndDelicious = false
ornagesAndOrange
和turnipsAndDelicious
被推斷爲Bool
由於他們是由Bool
字面量初始化來的。就像上面提到的Int
和Double
類型,當在聲明的時候你只須要設置一下他們的值true
或false
不須要聲明常量或者變量的類型。當初始化常量或者變量的時候若是要賦值的類型是已知的,就能夠觸發便以及的類型推斷,這使得Swift的代碼更加簡潔和易讀。
當你在寫條件語句好比if
語句的時候,布爾值顯得更加有用。
if turnipsAndDelicious { print("Mmm, tasty turnips!") } else { print("Eww, turnips are horrible.") } // 這裏打印的是:Eww, turnips are horrible.
關於條件語句,好比if
語句,能夠參考控制流
若是你在使用Bool值的時候賦了其餘類型的值,那麼swift由於類型安全就會報錯。下面的例子中就會報編譯的錯誤。
let i= 1 if i { // 這個例子不會編譯成功,會報錯(報錯緣由是 判斷的值不是bool類型) }
然而,下面的例子是合法的:
let i = 1 if i == 1 { // 這個例子能編譯成功不報錯。由於這裏i == 1 是一個判斷語句 }
由於等式i == 1
的結果是一個Bool
類型的值,因此第二個例子可以經過類型檢查。像i == 1
這樣類型的比較,參考 基本操做符。
和swift中其餘類型安全的例子同樣,這個方法避免了一些偶然的錯誤而且保證了代碼的目的老是清晰的。
元組(Truples)就是把多個值組合成一個複合值。元組中的成員並不必定是相同類型的數據,它們能夠是任意類型的數據。
在這個例子中(404,"Not Found")
就是一個表明HTTP
狀態碼的元組。HTTP
狀態碼是當你請求網頁的時候,web服務器返回的一個特殊值。若是請求的網頁不存在就會返回狀態碼404 NOT Found
。
let http404Error = (404,"Not Found") // http404Error的類型是(Int,String)的元組,值是(404, "Not Found")
(404,"Not Found")
這個元組把Int
和String
的值放到一塊兒組合起來表示HTTP
請求的狀態碼的兩部分:一個數組和另一個可讀的描述。它被描述爲一個類型爲(Int,String)
的元組。
你能夠把任意順序的類型組合爲一個元組,這個元組能夠你須要的任意類型的數據。你能夠建立一個類型爲(Int,Int,Int)
或者(String,Bool)
或者其餘的任何你想建立任意組合的元組。
你能夠將元組的內容分解爲單獨的常量或者變量,而後你就能夠正常使用它們了。
let (statusCode, statusMessage) = http404Error print("The status code is \(statusCode)") //輸出的狀態碼爲 404 print("The status message is \(statusMessage)") // 輸出的狀態描述爲 Not Found
若是你只須要元組中的其中一個值,那麼分解的時候你能夠用_
將不須要的部分省略掉。
let (justTheStatusCode,_) = http404Error print("The status code is \(justTheStatusCode)") // 輸出的狀態碼爲 404
此外,你還能夠用下標來訪問元組中的某個值,元組中的下標從0開始。
print("The status code is \(http404Error.0)") //輸出的狀態碼爲 404 print("The status message is \(http404Error.1)") // 輸出的狀態描述爲 Not Found
你能夠在定義元組的時候給單個元組進行命名
let http200Status = (statusCode:200,description:"OK")
當元組中的元素命名後,你能夠經過名字來獲取對應的元素的值。
print("The status code is \(http200Status.statusCode)") ////輸出的狀態碼爲 200 print("The status message is \(http200Status.description)") // 輸出的狀態描述爲 OK
元組在用做函數返回值的時候顯得尤其重要。已給獲取網頁請求狀態地方函數能夠會返回一個(Int,String)
元組來描述網絡請求的狀態。這和只能返回一個值進行比較來講。一個包含兩個不一樣類型值的元組返回地方信息更有用。瞭解更多請參考函數與返回值。
注意:
元組在組織臨時值的時候頗有用,它們並不適合用到複雜的數據結構裏。若是你的數據結構不是臨時的使用,那麼請使用類或者結構體而不是用元組。瞭解更多,請參考類與結構體。
當處理值缺失狀況的時候,你能夠用可選類型來表示。可選類型代表有兩種可能性:或者有值,你能夠解析這個可選類型來訪問這個值。或者這個值不存在。
注意:
在C
語言和Objective-C
語言中不存在可選類型這個概念。在Objective-C
語言中最接近的是一個方法中不要麼返回一個對象,要麼返回nil
,nil
表示缺乏一個合法的對象。然而,這隻對對象起做用,對於結構體,基本的C數據類型以及枚舉值都不起做用。對於這些類型,Objective-C
方法中通常會返回一個特殊值(好比NSNotFound)來暗示值的缺失。這種方法假設方法的調用者知道並對這些特殊值進行判斷。然而,Swift的可選類型讓你明白任意類型額值缺失,並不須要一個特殊的常量。
這裏有一個關於可選值是怎麼被用做當作缺省值的例子,Swift中整型中有一個構造器,做用是將一個String
類型的值轉換成一個Int
類型的值。然而,並非全部的字符串都可以轉化爲整型。字符串123
能夠被轉化爲整型123
,可是字符串Hello,world
不能被轉化爲整型。
下面的例子中使用這種便利構造器將String
轉換成Int
類型。
let possibleNumber = "123" let convertedNumber = Int(possibleNumber) //這裏的convertedNumber 被編譯器推斷爲'Int'類型,或者類型 ‘optional Int’
由於這個構造器也可能失敗,因此它的返回了一個可選類型的(optional)Int
而不是一個整型。一個可選的Int
類型寫做Int?
而不是Int
。這裏的問號包含的值是可選類型,也就是說可能包含Int;類型的值也可能不包含。(不能包含其餘的類型,好比說Bool
類型的值或者String類型的值,它只能是Int
類型,或者不存在這個類型。)
你能夠給一個不存在的可選類型的變量賦值爲nil
:
var serverResponseCode:Int? = 404 // serverResponseCode中包含了一個可選的Int類型的值404 serverResponseCode = nil // 這裏serverResponseCode的值爲nil(值不存在)
注意:
你不可以把nil
用在非可選的變量和常量上。若是你的代碼中存在常量或者變量值缺省的狀況,那麼在聲明的時候就聲明爲可選變量或者常量。
若是你不提供可選類型的變量的初始值,那麼變量會自動設置爲nil
。
var surveyAnswer:String? //這裏surveyAnswer將會被自動設置爲nil
注意:Swift
中的nil
和Objective-C
中的nil
意義不同。在Objective-C
中,nil是一個指向不存在對象的一個指針。在Swift
中,nil
不是一個指針,它是一個肯定類型的值。任何類型的可選狀態均可以被設置爲nil
,不只僅是對象類型的數據。
你可使用if語句和nil來判斷比較已給可選值是否包含值。你可使用(==
)以及(!=
)等於以及不等於兩個操做符來判斷一個可選值是否包含值。
若是一個可選類型是有值的,那麼它被認爲不等於nil
。
if convertedNumber != nil { print("convertedNumber contains some integer value.") } // 輸出convertedNumber contains some integer value.
當你肯定這個可選值確實包含值的時候,你能夠在可選的名字後面加一個!
來獲取值。
這個感嘆號表示我知道這個值有可選值,請使用它。這種被稱爲可選值的強制類型解析。
if convertedNumber != nil { print("convertedNumber has an integer value of \(convertedNumber).") } //輸出的是 convertedNumber has an integer value of 123.
更多關於if
條件語句的介紹,請參考控制流。
注意:
使用!
來獲取一個不存在的值可能會致使運行時的錯誤。在進行強制類型解析!
的時候要注意,確保可選類型必定要包含一個不爲nil
的值。
使用可選綁定來找出一個可選類型是否包含值,若是包含,若是包含就把值賦給一個臨時變量或者常量。可選綁定能夠用在if和while等條件語句中,這條語句不只僅能夠判斷可選類型中是否有值,同時也能夠將可選類型中的值賦給一個常量或者變量。關於if和while 語句,。請參考控制流。
像下面同樣用if語句寫一個可選綁定:
if let constantName = someOptional { statements }
你能夠像上面那樣使用可選綁定來重寫在例子可選類型中列舉的possibleNumber
例子。
if let actualNumber = Int(possibleNumber) { print("\'\(possibleNumber)\' has an integer value of \(actualNumber)") } else { print("\'\(possibleNumber)\' could not be converted to an integer") } // 輸出 123 has an integer value of 123
這段代碼能夠被這樣來解讀:
若是Int(possibleNumber)
返回的可選Int
包含的一個值,建立一個新的叫作actualNumber
的常量並將包含的值賦給它。
若是轉換成功,那麼actualNumber
常量能夠在if
語句的第一個分支中使用。它已經被可選類型包含的值初始化過,這裏就不須要再變量的後面添加!來進行強制解析獲取它的值了。在這個例子中,actualNumber
只是被用來輸出轉換的結果。
常量和變量均可以使用可選類型綁定。若是你想在if
的第一個分支語句中使用actualNumber
,那麼你能夠把判斷條件改成if var actualNumber
這裏就把可選類型中包含的值就被賦值給一個變量而不是一個常量。
你能夠在if
語句中使用多個可選綁定或者Bool
類型來做爲條件判斷,它們以前用逗號隔開。若是可選類型中任意一個值爲nil
或者Bool
類型中判斷結果爲false
,那麼整個if語句的條件判斷就會被認爲是false
。下面例子中的if
語句是等價的:
if let firstNumber = Int("4"),let secondNumber = Int("42"),firstNumber < secondNumber && secondNumber < 100 { print("\(firstNumber) < \(secondNumber) < 100") } // 打印的結果是:4 < 42 < 100 if let firstnumber = Int("4") { if let secondnumber = Int("42") { if firstnumber < secondnumber && secondnumber < 100 { print("\(firstnumber) < \(secondnumber) < 100") } } } // 打印的結果是:4 < 42 < 100
注意:
在if語句中建立的常量和變量的可選綁定,只能在body中使用。相反,在guard語句中建立的常量和變量的可選綁定,只有在guard語句以外可以取到值,請參參考提早退出。
就像上面描述的同樣,可選類型暗示了常量和變量能夠沒有值,可選類型經過if語句來判斷是否有值,若是有值的話能夠經過可選綁定來進行值的解析。
有時候在程序的結構中,在第一次被賦值之後,能夠肯定一個可選的類型老是有值。在這種狀況下,每次都進行判斷和解析可選值是很低效的,由於能夠肯定這個值是老是存在的。
這種類型的可選狀態被定義爲隱式解析可選類型implicitly unwrapped optionals
。把可選類型(String?
)後面的問號改成(String!
)歎號來聲明一個隱式解析可選類型。
當可選類型在第一次被賦值之後就能夠肯定一直有值的時候,隱式解析可選類型顯得頗有用。隱式解析可選類型主要被用在Swift中類的構造器中,請參考無主引用以及隱式解析可選屬性。
一個隱式解析可選類型實際上就是一個普通的可選類型,可是能夠被當作非可選類型來使用,並不須要每次都是用解析來獲取可選值。下面的例子中展現了可選類型String
和隱式解析可選類型String
行爲之間的區別。
let possibleString:String? = "An optional string." let forcedString:String = possibleString! //須要用感嘆號來獲取值 let assumedString:String! = "An implicitly unwrapped optional string." let implicitString:String = assumedString // 不須要用感嘆號就能獲取值
你能夠把隱式解析可選類型當作一個能夠自動解析的可選類型。你要作的就是在聲明的時候把感嘆號放到類型的結尾,而不是放到每次取值的可選名字的結尾。
注意:
若是你在隱式可選類型中沒有值的時候嘗試取值,那麼會觸發運行時的錯誤。這和你在沒有值的普通可選類型後面添加一個歎號同樣。
你仍然能夠把隱式解析可選類型當作普通的可選類型來判斷它是否包含值:
if assumedString != nil { print(assumedString!) } // 打印出 An implicitly unwrapped optional string.
你能夠在單個語句的可選綁定類型中使用隱式解析可選類型來檢查分析它的值:
if let definiteString = assumedString { print(definiteString) } // 打印出 An implicitly unwrapped optional string.
注意:
若是一個變量在以後可能會是nil
的時候,不要使用隱式解析可選類型。若是你須要在變量的聲明週期中判斷是否爲nil
的時候,使用普通可選類型。
你可使用錯誤處理(error handling
)來應對程序運行過程當中可能會出現的錯誤狀況。
與可選值不同的是,運用值的存在與缺失來表達函數執行的成功與失敗,錯誤處理能夠推斷出失敗的緣由。並能夠傳播到程序的其餘地方。
當一個函數遇到出現錯誤條件的時候,它能拋出錯誤。調用函數方法的地方能拋出異常併合理的響應。
func canThrowAnError () throws { // this function may or may not throw an error }
一個函數在聲明中添加一個throws
關鍵字是的時候來拋出錯誤消息。當一個函數可能會拋出異常的時候,你應該在表達式中使用前置try
關鍵詞。
Swift
會自動將錯誤傳播到當前的範圍直到它們被catch
句子來處理。
do { try canThrowAnError() // no error was thrown } catch { // an error was thrown }
一個do
語句建立了一個新的做用域,它容許錯誤被傳遞到一個或者多個catch
語句中。
這是一個如何運用錯誤處理來應對不一樣錯誤狀況的例子:
do { try makeASandwich() eatASandwich() } catch SandwichError.outOfCleardishes { washDishes() } catch SandwichError.missingTngredients(let ingredients) { buyGroceries(ingredients) }
在這個例子中,makeASandwich()
函數會拋出一個錯誤消息條件是若是沒有乾淨的盤子或者某個原料的缺失。因爲makeASandwich()
可能會拋出錯誤,因此函數調用被包在了try
語句中。將函數包在一個do
語句中,那麼任何被拋出的錯誤都會被傳播到catch
語句中。
若是沒有錯誤被拋出,那麼eatASandwich()
函數會被調用。若是一個匹配SandwichError.outOfCleardishes
的錯誤被拋出,那麼會執行washDishes()
這個函數,若是異常SandwichError.missingTngredients
被捕獲到,那麼buyGroceries(_:)
函數將會被調用,而且會使用catch
所捕獲到的關聯值String
做爲參數。
拋出,捕獲以及傳播錯誤等,會在錯誤處理的章節中說明。
斷言和先決條件是在運行時進行檢查的。你能夠用它們來檢查在執行後面代碼的以前是否一個必要的條件已經知足了。若是斷言或者先決條件中的bool
值是true
的時候,那麼代碼會像往常同樣執行。若是條件判斷爲false
,當前程序的狀態是無效的,代碼的執行會結束,你的app會被終止。
你使用斷言和先決條件來表達你作的假設和你在編碼時候的但願執行的方式。你能夠將這些包含在代碼中。斷言幫助你在開發階段找到錯誤和不正確的假設,先決條件幫助你在在生產環境中發現存在的問題。
除了在運行時驗證你的指望值,斷言和先決條件也變成了你代碼中一種有用的文檔形式。和上面討論的錯誤處理不一樣,斷言和先決條件不是用來處理能夠恢復或者能夠預期的錯誤。由於一個斷言失敗代表了程序正在處於一個無效的狀態,沒有辦法來捕獲一個失敗的斷言。
使用斷言和先決條件不是一個可以避免出現程序無效狀態的編碼方法。然而,若是一個無效狀態的程序產生快了。斷言能夠強制檢查你的數據和程序狀態,使程序按照預測中的被終止,並幫助咱們更簡單的對這個問題進行調試。一旦遇到無效的狀態,程序就會被終止,防止無效的狀態對程序形成進一步的傷害。
斷言和先決條件的不一樣之處在於它們何時進行檢測。斷言僅僅在調試的時候運行,可是先決條件不只僅在調試的時候能運行在生產環境下也能運行。在生產環境下,斷言條件不會被評估。這意味着你能夠在開發階段多使用斷言,這些斷言在生產條件下不會形成影響。
你能夠用Swift標準庫的函數assert(_:_:file:line:)
來編寫一個斷言。
你向這個函數傳入一個判斷結果爲true和false的表達式以及一條錯誤狀況下展現的信息。例如:
let age = -3 assert(age >= 0,"A person's age can't be less than zero.") // 這個斷言會失敗 由於一我的的年齡不可能小於0(把斷言中的語句變爲age <= 0,就不會走這個斷言)
在這個例子中,只有age >= 0
爲true
也就是說age
的值爲非負數的時候,代碼纔會繼續執行。若是age的值爲負數,就像上面代碼中的同樣,那麼,age >= 0
爲false
,斷言失敗,使得應用被終止運行。
你也能夠省略掉斷言的提示信息,例如:當斷言條件可能會重複執行的時候
assert(age >= 0)
若是代碼已經被檢查過,你可使用函數assertionFailure(_:file:line:)
來代表斷言失敗了。例如:
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.") }
當一個條件可能爲假,可是繼續執行下去要求條件必須爲真的時候,須要使用先決條件。例如:使用先決條件來判斷下標有沒有越界,或者來檢查是否將一個正確的參數傳給了函數。
你可使用函數precondition(_:_:file:line:)
來寫一個先決條件。向這個函數傳入一個結構爲true或者false的表達式以及一條錯誤條件下顯示信息。例如:
// 下標的實現 precondition(index > 0, "Index must be greater than zero.")
你能夠調用函數preconditionFailure(_:file:line:)來代表出現了一個錯誤,例如:switch
的進入了default
分支,全部的有效輸入數據都應該被其餘分支所處理而不是默認的default
分支。
注意:
若是你使用不檢查的模式(-Ounchecked)進行編譯,先決條件將不會進行檢查。編譯器會假設全部的先決條件都是true
,這將優化你的代碼。然而致命的錯誤函數(_:file:line:)
老是中斷執行,不管你進行什麼樣的優化設置。
在設計原型和早期的開發階段你可使用致命的錯誤函數(_:file:line:)
,這個階段只是對方法的聲明,
可是沒有具體的實現。你能夠在方法fatalError("Unimplemented")
進行具體實現。由於fatalError
不會像斷言和先決條件那樣能夠被優化,因此你能夠確保當代碼執行到一個沒有實現的方法是的時候,程序會被中斷。
更多swift4.1翻譯請查看github。
QQ技術交流羣:214541576
微信公衆號:shavekevin
開發者頭條:
熱愛生活,分享快樂。好記性不如爛筆頭。多寫,多記,多實踐,多思考。