雖然Swift是一個為開發iOS和OS X app設計的全新編程語言,但是Swift的很多特性還是跟C和Objective-C相似。
Swift也提供了與C和Objective-C類似的基礎數據類型,包括整形Int、浮點數Double和Float、布爾類型Bool以及字符串類型String。Swift還提供了兩種更強大的基本集合數據類型,Array和Dictionary,更詳細的內容可以參考:Collection Types。
跟C語言一樣,Swift使用特定的名稱來定義和使用變量。同樣,Swift中也可以定義常量,與C語言不同的是,Swift中的常量更加強大,在編程時使用常量能夠讓代碼看起來更加安全和簡潔。
除了常見的數據類型之外,Swift還集成了Objective-C中所沒有的“元組”類型,可以作為一個整體被傳遞。元組也可以成為一個函數的返回值,從而允許函數一次返回多個值。
Swift還提供了可選類型,用來處理一些未知的不存在的值。可選類型的意思是:這個值要麼存在,並且等於x,要麼根本不存在。可選類型類似於Objective-C中指針的nil值,但是nil只對類(class)有用,而可選類型對所有的類型都可用,並且更安全。可選類型是大部分Swift新特性的核心。
可選性類型只是Swift作為類型安全的編程語言的一個例子。Swift可以幫助你更快地發現編碼中的類型錯誤。如果你的代碼期望傳遞的參數類型是String的,那麼類型安全就會防止你錯誤地傳遞一個Int值。這樣就可以讓編程人員在開發期更快地發現和修復問題。
常量和變量
常量和變量由一個特定名稱來表示,如maximumNumberOfLoginAttempt 或者 welcomeMessage。常量所指向的是一個特定類型的值,如數字10或者字符”hello”。變量的值可以根據需要不斷修改,而常量的值是不能夠被二次修改的。
常量和變量的聲明
常量和變量在使用前都需要聲明,在Swift中使用let關鍵詞來聲明一個常量,var關鍵詞聲明一個變量。如下面例子:
復制代碼代碼如下:
以上代碼可以理解為:
聲明一個叫maximumNumberOfLoginAttempts的值為10的常量。然後聲明一個變量currentLoginAttempt初始值為0。
在這個例子中,最大的登錄嘗試次數10是不變的,因此聲明為常量。而已經登錄的嘗試次數是可變的,因此定義為變量。也可以在一行中聲明多個變量或常量,用,號分隔:
復制代碼代碼如下:
注:如果一個值在之後的代碼中不會再變化,應該用let關鍵詞將它聲明為常量。變量只用來存儲會更改的值。
類型注解
在聲明常量和變量時,可以使用注解來注明該變量或常量的類型。使用:號加空格加類型名在變量或常量名之後就可以完成類型注解。下面的例子就是聲明了一個變量叫welcomeMessage,注解類型為字符串String:
var welcomeMessage: String
分號 “:” 在這的作用就像是在說:…是…類型的,因此上述代碼可以理解為:
聲明一個叫welcomeMessage的變量,它的類型是String
這個類型注解表明welcomeMessage變量能無誤地存儲任何字符串類型的值,比如welcomeMessage = “hello”
注:實際編程中很少需要使用類型注解,定義常量或者變量的時候Swift已經根據初始化的值確定了類型信息。Swift幾乎都可以隱式的確定變量或常量的類型,詳見:Type Safety and Type Inference。而上面的welcomeMessage的例子中,初始化值沒有被給出,所以更好的辦法是指定welcomeMessage變量的類型而不是讓Swift隱式推導類型。
常量和變量的命名
Swift中可以使用幾乎任何字符來作為常量和變量名,包括Unicode,比如:
復制代碼代碼如下:
但是名稱中不能含有數學符號,箭頭,無效的Unicode,橫線-和制表符,且不能以數字開頭,盡管數字可以包含在名稱裡。一旦完成了聲明,就不能再次聲明相同名稱的變量或常量,或者改變它的類型。變量和常量也不能互換。
注:如果你想用Swift保留字命名一個常量或者變量,你可以用 ` 符號把命名包圍起來。盡管如此,除非處於特別的意圖,盡量不要使用保留字作為變量/常量名。
可以改變變量的值為它聲明的類型的其它值,如下的例子裡,變量friendlyWelcome的值從“Hello!”被修改為”Bonjour!”:
復制代碼代碼如下:
與變量不同的是,常量的值一旦確定就不能修改。如果想嘗試改變一個常量的值,編譯代碼時就會報錯
復制代碼代碼如下:
輸出常量和變量
Swift使用println來輸出變量或者常量:
復制代碼代碼如下:
println函數一般輸出一個字符串
復制代碼代碼如下:
注:關於格式化字符的詳見String Interpolation
注釋
不參與編譯的語句稱為注釋,注釋可以提示你代碼的意圖。Swift中的注釋和C語言中的一樣,有單行注釋
復制代碼代碼如下:
分號
和其它一些編程語言不同,Swift不需要使用分號 ; 來分隔每一個語句。當然你也可以選擇使用分號,或者你想在一行中書寫多個語句。
復制代碼代碼如下:
整數
整數就是像42和-23這樣不帶分數的數字,包括有符號(正數,負數,0)和無符號(正數,0)。Swift提供了8、16、32和64位的數字形式,和C語言類似,可以使用8位的無符號整數UInt8,或者32位的整數Int32.像其他Swift類型一樣,這些類型名的首字母大寫。
整數邊界
使用min或max值來獲取該類型的最大最小值,如:
復制代碼代碼如下:
Int類型
一般來說,編程人員在寫代碼時不需要選擇整數的位數,Swift提供了一種額外的整數類型Int,是和當前機器環境的字長相同的整數位數
1.在32位機器上,Int和Int32一樣大小
2.在64位機器上,Int和Int64一樣大小
除非你確實需要使用特定字長的正數,盡量使用Int類型。這保證了代碼的可移植性。即使在32位的平台上,Int也可以存儲-2,147,483,648 到2,147,483,647范圍內的值,這對大部分正數來講已經足夠了。
UInt類型
Swift還提供了一種無符號類型UInt,同理也是和當前機器環境的字長相等。
1.在32位機器上,UInt和UInt32一樣大小
2.在64位機器上,UInt和UInt64一樣大小
注:只有顯式的需要指定一個長度跟機器字長相等的無符號數的時候才需要使用UInt,其他的情況,盡量使用Int,即使這個變量確定是無符號的。都使用Int保證了代碼的可移植性,避免了不同數字類型之間的轉換。
5、浮點數
浮點數就是像3.14159,0.1,-273.15這樣帶分數的數字。浮點數可以表達比Int范圍更廣(更大或更小)的數值。swift支持兩種帶符號浮點數類型:
1.Double類型能表示64位的有符號浮點數。當需要表的數字非常大或者精度要求非常高的時候可以使用Double類型。
2.Float類型能表示32為的有符號浮點數。當需要表達的數字不需要64位精度的時候可以使用Float類型。
注 Double 至少有15位小數,Float至少有6位小數。合適的浮點數小數位數取決於你代碼裡需要處理的浮點數范圍。
6、類型安全和類型推導
Swift是一種類型安全的語言。類型安全就是說在編程的時候需要弄清楚變量的類型。如果您的代碼部分需要一個字符串,你不能錯誤地傳遞一個整數類型。
因為Swift是類型安全的,它會在編譯的時候就檢查你的代碼,任何類型不匹配時都會報錯。這使得編程人員能夠盡快捕獲並盡可能早地在開發過程中修正錯誤。
類型檢查可以在使用不同類型的值時幫助避免錯誤。但是,這並不意味著你必須指定每一個常量和變量所聲明的類型。如果不指定你需要的類型,Swift使用類型推導來指定出相應的類型。類型推導使編譯器在編譯的時候通過你提供的初始化值自動推導出特定的表達式的類型。
類型推導使Swift比起C或Objective-C只需要更少的類型聲明語句。常量和變量仍然顯式類型,但大部分指定其類型的工作Swift已經為你完成了。
當你聲明一個常量或變量並給出初始值類型的時候,類型推導就顯得特別有用。這通常是通過給所聲明的常量或變量賦常值來完成的。 (常值是直接出現在源代碼中的值,如下面的例子42和3.14159 。 )
例如,如果您指定42到一個新的常數變量,而不用說它是什麼類型,Swift推斷出你想要的常量是一個整數,因為你已經初始化它為一個整數
復制代碼代碼如下:
數值量表達
整型常量可以寫成:
1.一個十進制數,不帶前綴
2.一個二進制數,用前綴0b
3.一個八進制數,用0o前綴
4.一個十六進制數,以0x前綴
所有如下用這些整型常量都可以來表達十進制值的17:
復制代碼代碼如下:
浮點可以是十進制(不帶前綴)或十六進制(以0x前綴),小數點的兩側必須始終有一個十進制數(或十六進制數)。他們也可以有一個可選的指數,由一個大寫或小寫e表示十進制浮點數表示,或大寫/小寫p表示十六進制浮點數
帶指數exp的十進制數,實際值等於基數乘以10的exp次方,如:
◎1.25e2表示1.25×102,或者125.0.
◎1.25e-2表示1.25×10-2,或者0.0125.
帶指數exp的十六進制數,實際值等於基部數乘以2的exp次方,如:
◎0xFp2表示15×22,或者60.0.
◎0xFp-2表示15×2-2,或者3.75.
所有如下這些浮點常量都表示十進制的12.1875:
復制代碼代碼如下:
數值類型轉換
為代碼中所有通用的數值型整型常量和變量使用Int類型,即使它們已知是非負的。這意味著代碼中的數值常量和變量能夠相互兼容並且能夠與自動推導出的類型相互匹配。
只有因為某些原因(性能,內存占用或者其他必須的優化)確實需要使用其他數值類型的時候,才應該使用這些數值類型。這些情況下使用顯式指定長度的類型有助於發現值范圍溢出,同時應該留下文檔。
整數轉換
可以存儲在一個整數常量或變量的范圍根據每個數值類型是不同的。一個Int8常量或變量可以存儲范圍-128到127之間的數,而一個UInt8常量或變量可以存儲0到255之間的數字。錯誤的賦值會讓編譯器報錯:
復制代碼代碼如下:
要轉換一個特定的數字類型到另一個,你需要定義一個所需類型的新變量,並用當前值初始化它。在下面的例子中,常量twoThousand是UInt16類型的,而常量one是UINT8類型的。它們不能被直接相加的,因為類型不同。相反的,該??示例調用UInt16(one)來創建一個用變量one的值初始化的UInt16類型的新變量,並且使用這個值來代替原來的值參與運算:
復制代碼代碼如下:
SomeType(ofInitialValue)是Swift默認的類型轉換方式。實現上看,UInt16的有一個接受UINT8值的構造器,這個構造器用於從現有UInt8構造出一個新的UInt16的變量。你不能傳入任意類型的參數,它必須是一個類型的UInt16初始化能接受的類型。如何擴展現有類型,規定接受新的類型(包括你自己的類型定義)可以參見Extensions。
整數和浮點數轉換
整數和浮點類型之間的轉化必須顯式聲明:
復制代碼代碼如下:
注:數值類型常量/變量的類型轉換規則和數字類型常值的轉換規則不同。常值3可以直接與常值0.14159相加,因為常值沒有一個明確的類型。他們的類型是被編譯器推導出來的。
類型別名
類型別名為現有類型定義的可替代名稱。你可以使用typealias關鍵字定義類型別名。類型別名可以幫助你使用更符合上下文語境的名字來指代一個已存在的類型,比如處理一個外來的有指定長度的類型的時候:
復制代碼代碼如下:
布爾類型
Swift中的布爾類型使用Bool定義,也被稱為Logical(邏輯)類型,可選值是true和false:
復制代碼代碼如下:
像if語句這樣的條件語句,我們會在之後的章節ControlFlow有詳細介紹。 Swift的類型安全策略會防止其他非布爾類型轉換為布爾類型使用,比如
復制代碼代碼如下:
元組類型
元組類型可以將一些不同的數據類型組裝成一個元素,這些數據類型可以是任意類型,並且不需要是同樣的類型。
在下面的例子中,(404, “Not Found”) 是一個HTTP狀態碼。HTTP狀態碼是請求網頁的時候返回的一種特定的狀態編碼。404錯誤的具體含義是頁面未找到。
復制代碼代碼如下:
編程人員可以隨意地創建自己需要的元組類型,比如 (Int, Int, Int), 或者(String, Bool)等。同時組成元組的類型數量也是不限的。 可以通過如下方式分別訪問一個元組的值:
復制代碼代碼如下:
可選類型
在一個值可能不存在的時候,可以使用可選類型。這種類型的定義是:要麼存在這個值,且等於x,要麼在這個值 不存在。
注:這種類型在C和Objective-C中是不存在的,但是Objective-C中有一個相似的類型,叫nil,但是僅僅對對象有用。對其他的情況,Object-C方法返回一個特殊值(比如NSNotFound)來表明這個值不存在。這種方式假設方法調用者知道這個特殊值的存在和含義。Swift的可選類型幫助你定義任意的值不存在的情況。
下面給出一個例子,在Swift中String類型有一個叫toInt的方法,能夠將一個字符串轉換為一個Int類型。但是需要注意的是,不是所有的字符串都可以轉換為整數。比如字符串”123″可以轉換為123,但是”hello, world”就不能被轉換。
復制代碼代碼如下:
if語句和強制解包
編程人員可以使用if語句來檢測一個可選類型是否包含一個特定的值,如果一個可選類型確實包含一個值,在if語句中它將返回true,否則返回false。如果你已經檢測確認該值存在,那麼可以使用或者輸出它,在輸出的時候只需要在名稱後面加上感歎號(!)即可,意思是告訴編譯器:我已經檢測好這個值了,可以使用它了。如:
復制代碼代碼如下:
像if語句這樣的條件語句,我們會在之後的章節ControlFlow有詳細介紹。
選擇綁定
選擇綁定幫助確定一個可選值是不是包含了一個值,如果包含,把該值轉化成一個臨時常量或者變量。選擇綁定可以用在if或while語句中,用來在可選類型外部檢查是否有值並提取可能的值。if和while語句詳見ControlFlow。
方法如下:
復制代碼代碼如下:
如果轉換是成功的,那麼actualNumber常量在if的第一個分支可用,並且被初始化為可選類型包含的值,同時也不需要使用!前綴。這個例子裡,actualNumber只是簡單的被用來打印結果。
常量和變量都可以用來做可選綁定。如果你想要在if第一個分支修改actualNumber的值,可以寫成if var actualNumber, actualNumber就成為一個變量從而可以被修改。
nil
可以給可選類型指定一個特殊的值nil:
復制代碼代碼如下:
隱式解包可選類型
在上面的例子中,可選類型表示一個常量/變量可以沒有值。可選類型可以被if語句檢測是否有值,並且可以被可選綁定解包。
但是在一些情況下,可選類型是一直有效的,那麼可以通過定義來隱式地去掉類型檢查,強制使用可選類型。這些可選類型被成為隱式解包的可選類型。你可以直接在類型後面加! 而不是?來指定。
隱式解包的可選類型主要用在一個變量/常量在定義瞬間完成之後值一定會存在的情況。這主要用在類的初始化過程中,詳見Unowned References and Implicitly Unwrapped Optional Properties.
隱式解包的可選類型本質是可選類型,但是可以被當成一般類型來使用,不需要每次驗證值是否存在。如下的例子展示了可選類型和解包可選類型之間的區別。
復制代碼代碼如下:
let assumedString: String! = "An implicitly unwrapped optional string."
println(assumedString) // no exclamation mark is needed to access its value
// prints "An implicitly unwrapped optional string."
你可以把隱式解包可選類型當成對每次使用的時候自動解包的可選類型。即不是每次使用的時候在變量/常量後面加!而是直接在定義的時候加。
注:如果一個隱式解包的可選類型不包含一個實際值,那麼對它的訪問會拋出一個運行時錯誤。在變量/常量名後面加!的情況也是一樣的。
你依然可以把解包可選類型當成正常的可選類型來探測是否有值。
復制代碼代碼如下:
if let definiteString = assumedString {
println(definiteString)
}
// prints "An implicitly unwrapped optional string."
斷言
可選類型讓編程人員可以在運行期檢測一個值是否存在,然後使用代碼來處理不存在的情況。但是有些情況下,如果一個值 不存在或者值不滿足條件會直接影響代碼的執行,這個時候就需要使用斷言。這種情況下,斷言結束程序的執行從而提供調試的依據。
使用斷言調試
斷言是一種實時檢測條件是否為true的方法,也就是說,斷言假定條件為true。斷言保證了後續代碼的執行依賴於條件的成立。如果條件滿足,那麼代碼繼續執行,如果這個條件為false,那麼代碼將會中斷執行。
在Xcode中,在調試的時候如果中斷,可以通過查看調試語句來查看斷言失敗時的程序狀態。斷言也能提供適合的debug信息。 使用全局函數assert來使用斷言調試,assert函數接受一個布爾表達式和一個斷言失敗時顯示的消息,如:
復制代碼代碼如下:
在這個例子中,只有當age >= 0的時候,條件被判定為true,但是age = -3,所以條件判定為false,輸出錯誤日志 “A person's age cannot be less than zero”。
當然錯誤日志也可以省略,但是這樣不利於調試,如
復制代碼代碼如下:
當需要檢測一個條件可能是false,但是代碼運行必須返回true的時候使用。下面給出了一些常用場景,可能會用到斷言檢測:
◎傳遞一個整數類型下標的時候,比如作為數組的Index,這個值可能太小或者太大,從而造成數組越界;
◎傳遞給函數的參數,但是一個無效的參數將不能在該函數中執行
◎一個可選類型現在是nil,但是在接下來的代碼中,需要是非nil的值才能夠繼續運行。
詳見Subscripts和Functions
注:斷言會導致程序運行的中止,所以如果異常是預期可能發生的,那麼斷言是不合適的。這種情況下,異常是更合適的。斷言保證錯誤在開發過程中會被發現,發布的應用裡最好不要使用。