在這一章里,我們會學習Swift基本的知識:創建變量,集合,循環體以及條件語句。這一章將會介紹Swift中最重要的知識,這樣你能更開的開發程序。
什么是Swift?
Swift是蘋果公司開發的新的編程語言,在2014年六月的AWDC上推出的。過去20年里蘋果公司使用Objective-C來開發程序,而Swift的推出是為了讓編程更加簡單明了,為初學者減少了障礙,讓所有人都可以開發APP。
Playgrounds
Swift最令人幸福的新特性之一就是Playground,可以快速簡單的編寫程序,能夠立即檢測代碼正確性。我強烈推薦你在閱讀此書的時候,電腦上會一直開著一個Playground文件,寫下書中的代碼和例子,這樣不僅能幫你看到代碼是如何運行的,更能提供你的記憶力。
現在,新建一個Playground文件吧(圖3-1)。
Page 55
打開Xcode,點擊File -> New -> File ,點擊iOS下的Source,點擊Playground,最后點擊Next(圖3-2)。
Page 56 | Chapter3:Diving into Swift
選擇要保存的文件夾,可以保存在上一章節中已經建好的Programming文件夾,輸入文件名,點擊Create(圖3-3)。現在,你有了一個Playground文件了(圖3-4)。
Playgrounds | Page57
聲明變量(Creating Variables)
變量是可以改變的值,值是動態的。動態意味著一個值可以現在變化,也可以在將來變化。在swift中,用var
表示變量,這樣Xcode就知道你聲明的是一個變量。
變量用變量名表示,變量名關聯變量的值,這樣就意味著,變量的值發生改變后,變量名是不變的,可以一直用變量名來指示這個變量。變量名的命名方法遵循駝峰命名法。例如:
var numberOfYears
在變量名后面跟一個冒號,這是告訴Xcode你要聲明的這個變量的類型。類型就類似電影中的分類,有些是喜劇電影,有些是音樂劇、恐怖片、文藝。每個分類都有自己獨特的特性,但是它們都是電影。聲明變量的類型使用冒號,在冒號后面,寫上類型的關鍵詞。例如,聲明一個整型變量,用Int
:
var numberOfYears: Int
Page 58 | Chapter3:Diving into Swift
最后,你必須給這個變量設定一個初始值,這個初始值必須符合你設定的類型,否則,這個變量就無法聲明:
var numberOfYears: Int = 30
這里的等號是用了初始化一個變量。初始化表示給變化一個默認值。把這個過程想象成打開一個新玩具,卻忘記放電池,這個玩具沒法玩直到我們把電池放進去。你必須初始化你的變量,賦一個默認值,不然這個變量無法使用。
整型(Integers)
整型,整數的正值或者負值,用Int
表示。下面這行代碼,用var
表示這是一個變量,用favoriteNubmer
作為變量名,緊接著用一個冒號來聲明這個變量的類型。這行代碼顯示,這個變量的類型是整型,所以使用Int
。最后,這個變量的初始值設定為4,跟在等號的后面:
var favoriteNumber: Int = 4
浮點型(Float)
浮點型是指有小數點位的數值,用Float
表示。例如,下面這行代碼,用var
表示這是一個變量,用accountBalance
作為變量名,冒號聲明這個變量是Float
類型,最后,用等號表示這個變量的初始值是1203.51:
var accountBalance: Float = 1203.51
布爾型(Boolean)
布爾型的值,只有true
真或者false
假,兩種情況,用Bool
表示。例如,下面這行代碼,用var
表示這是一個變量,用isStudent
作為變量名,冒號后聲明這個變量是Bool
類型,最后,用等號表示這個變量的初始值是true:
var isStudent: Bool = true
字符串類型(Strings)
字符串類型是指字符,英文的字母單詞或者中文的漢字詞匯等字符,要用雙引號將字符串包含起來,用String
表示。例如,下面這行代碼,用var
表示這是一個變量,用firstName
作為變量名,冒號后聲明這個變量是String
類型,最后,用等號表示這個變量的初始值是Steve:
var firstName: String = "Steve"
Creating Variables | Page59
對象(Objects)
變量也可以表示對象,對象的類型就是類的名字。記住,類就是這個對象的藍圖,類里面包含了對象所有的屬性和行為。
下面這行代碼,用var
表示這是一個變量,用fastCar
作為變量名,冒號后聲明這個變量是對象類型,在這里,就是Car
,最后,用等號表示這個變量的初始值是一個新的車對象:
var fastCar: Car = Car()
常量(Constants)
有時候有些東西你確定它們是百分之百不會改變,比如你的生日。這時候,你可以用常量來代替變量。常量是用來處理那些不會改變的數值,一旦設定值后,在它的整個生命周期內,值都就不會再改變了。常量的值是靜態的,靜態意味著值在現在或者將來都不會改變。
定義一個常量和定義一個變量非常相似,唯一的區別是定義常量使用let
而定義變量使用var
。例如:
var numberOfYears: Int = 30`
let name: String = "Steve"
let isMale: Bool = true
var bankAccountBalance: Float = 1034.20
你會注意到name和isMale是常量,這些常量的值是永遠不會改變的。
你也許會問:“為什么我不直接把所有的常量都用變量表示,然后一直不改變變量的值,這個也和常量沒有什么區別了啊?” 恩,這樣也是可行的,只是這個方法違背了編程的最佳實踐原則。最佳實踐原則能夠為開發者和用戶提供更好的體驗。例如,使用一個常量代替變量能夠節省內存和電量,如果所有的開發者都踐行最佳實踐原則,這樣會給用戶提供更好的體驗。
Page 60 | Chapter3:Diving into Swift
類型推斷(Type Inference)
為每一個變量和常量聲明類型可是一件體力活,蘋果公司的工程師一直致力于讓開發者的工作更輕松。基于你提供的等號右邊的值,Swift可以自己判斷類型,也就是具有類型推斷的能力,這使得聲明變量更加容易。請見下面的例子:
var numberOfYears = 30
let name = "Steve"
let isMale = true
var bankAccountBalance = 1034.20
冒號和冒號后面的類型就不需要了,因為Swift可以根據等號右邊的值來推斷類型,然后自動設定變量的類型。這樣能節省不少時間,也能讓代碼更簡潔。
修改字符串(Modifying Strings)
Swift中的字符串類(String class)提供了不少簡便快捷的方法,例如uppercaseString
,可以使小寫字母改變為大寫字母。//后面展示的是改變后的字符串效果。
var favoriteFood: String = "Pasta"
favoriteFood = favoriteFood.uppercaseString //PASTA
當你設定favoriteFood變成favoriteFood.uppercaseString時,等號表明等號右邊的值賦值給等號左邊的變量,把這個過程拆解開來就是:
1. favoriteFood //"Pasta"
2. favoriteFood.uppercaseString //"PASTA"
3. favoriteFood = favoriteFood.uppercaseString //"PASTA"
4. favoriteFood //"PASTA"
Modifying Strings | Page61
大部分的代碼會按順序執行,第一行代碼運行完畢后,編譯器會運行第二行代碼,接著第三行代碼,依次進行。第一行代碼在沒有執行完畢之前,第二行代碼是不會執行的。
當然,也有lowercaseString方法,把所有的字母都變成小寫字母,還有capitalizedString方法,把所有的單詞的首字母大寫。
附加字符串(Appending Strings)
你可以在一個字符串變量的后面加上一串字符,也就是附加(appending):
var beach = "Beach"
beach = beach + "Ball" //"BeachBall"
一個字符串可以和另一個字符串相加,組成一個新的字符串。例如:
let firstName = "Steve"
var lastName = "Derico"
lastName = firstName + lastName //"SteveDerico"
還可以,在兩個字符串之間附加一個字符串。例如:
let firstName = "Steve"
let lastName = "Derico"
var fullName = firstName + " " + lastName
var favoriteMovie = " Back to The Future"
var movieString = " My name is " + fullName + " and my favorite movie is " + favoriteMovie //My name is Steve Derico and my favorite movie is Back To The Future
字符串中的變量(Variables in Strings)
使用字符串插入(string interpolation),可以直接在變量中增加字符串。字符串插入這個術語是指在一個字符串里使用占位符來產生一個字符串。程序運行后,這些占位符就會直接調用。在這里,字符串是用雙引號表示的,那么占位符是用\()
表示的,兩個括號中是需要插入的字符串。字符串插入這個方法可以將一個非字符串的變量方便地轉換為字符串類型:
let seatsPerRow = 25
let numberOfRows = 25
var seatsString = "In the theater, there are \(numberOfRows) rows and \(seatsPerRow) seats in each row." //In the theater, there are 15 rows and 25 seats in each other row.
Page 62 | Chapter3:Diving into Swift
集合(Collection)
在某些情況下,有必要將許多變量或常量更好地組織在一起,Swift提供2種集合類型來保存和組織這些變量。
數組(Arrays)
假設你想存儲過山車中站在排的人的名字,你該怎么做?你可以為在一排中的每一個人聲明一個變量,不過這樣就會有些麻煩,你也不知道在某個時刻有多少人是在一排上。為了解決這種麻煩,我們用到了數組。
數組(Array)是按照聚體順序存儲多個變量的容器。數組可以存儲幾乎無限的元素(item),同時每個元素都有一個數組下標,準確標明此元素在數組中的位置。可以這樣聲明一個數組:
var names: [ String ] = [ "Steve", "Jeff", "Andy", "Andrew", "Cole", "Mike", "Mikey" ]
開頭還是var
,接著是冒號,然后是方括號,方括號里是數組的類型,等號的右邊,用方括號括起來所有的數組元素,里面每個數組元素用逗號分開。
在Swift中,數組中所有的元素必須是同樣的類型,這以為著一個數組能存儲所有的字符串,如上面的例子,但是不能存儲整型和字符串2種不同的類型的元素。數組只能存儲同樣類型的變量。
對于一個既定的數組,Swift可以自行判斷出類型,沒有必要專門寫出數組的類型,所以上面的數組也可以寫成這樣:
var names = [ "Steve", "Jeff", "Andy" ]
Collections | Page63
查找數組(Navigating arrays)
(Navigating arrays是查找數組的意思嗎?導航數組?)
數組中的每個元素都有特定的位置或者下標,下標是從0開始的,第一個元素的下標是0,第二個元素的下標是1,第三個元素的下標是2,依此類推。獲取數組中的某個元素使用下面的格式:
names[0] // Steve
names[1] //Jeff
names[2] //"Andy
一開始可能不習慣零開頭,時間長了,就會下意識的認為是以零開頭了。下標都是以零開頭的。
使用count
方法可以獲得數組中所有元素的總數。最后一個元素的下標會比總數少了一:
names.count // 3
檢查數組元素是否為空,這個數組中是否有元素,使用isEmpty
方法:
var cats = [ "Big Kitty" ]
cats.isEmpty //false
修改數組(Modifying arrays)
用var聲明的數組是動態的可以按照需要改變,在數組最后一個元素后面附加一個元素使用append方法:
var names = [ "Steve", "Jeff", "Andy" ]
names.append ( "Wally" ) // [ "Steve", "Jeff", "Andy", "Wally" ]
也可以給你的數組增加一個數組:
Page 64 | Chapter3:Diving into Swift
var names = [ "Steve", "Jeff", "Andy", "Wally" ]
var parents = [ "Mike", "Adam", "Nick" ]
names = names + parents // [ "Steve", "Jeff", "Andy", "Wally", "Mike", "Adam", "Nick" ]
可以通過某個元素的下標來替換元素值,給這個元素賦新的值:
names[6] = "Sam"
還有一個insert
方法,可以在某個具體位置插入元素。插入元素后,此元素后面的元素的下標值都會自動增加1。
var names = [ "Steve", "Jeff", "Andy", "Wally", "Mike", "Adam", "Sam" ]
names.insert ( "Buster", atIndex: 2 ) // [ "Steve", "Jeff", "Buster", "Andy", "Wally", "Mike", "Adam", "Sam" ]
而刪減某個元素,使用removeAtIndex
方法:
var names = [ "Steve", "Jeff", "Buster", "Andy", "Wally", "Mike", "Adam", "Sam" ]
names.removeAtIndex(2) // [ "Steve", "Jeff", "Andy", "Wally", "Mike", "Adam", "Sam" ]
詞典(Dictionaries)
數組不是唯一的集合類型,詞典也可以存儲多個變量,用鍵(Key)和值(value)將多個變量組織在一起。鍵值的工作原理和你書架上的牛津大詞典類似,鍵(Key)是你要查找的單詞,而值(value)是這個單詞的釋義。詞典是無序存儲的,所以只能使用鍵(key)來獲取某個值(value),例如:
var homeruns : [ String : Int ] = [ "Posey" : 24, "Pagan" : 19, "Pence" : 15 ]
在這個例子中,有三個鍵(keys):"Posey"
, "Pagan"
, "Pence"
,每個鍵都有對應的值。提高相關的鍵,寫在中括號中,就能獲取相對應的值:
homeruns[ "Posey" ]
// 24
增加一對鍵值:
var homeruns : [ String : Int ] = [ "Posey" : 24, "Pagan" : 19, "Pence" : 15 ]
homeruns[ "Sandoval" ] = 10 // [ "Posey" : 24, "Pagan" : 19, "Pence" : 15, "Sandoval" : 10 ]
Collections | Page65
給鍵設定一個新值就可以改變詞典中的元素:
homeruns [ "Posey" ] = 36 // [ "Posey" : 36, "Pagan" : 19, "Pence" : 15, "Sandoval" : 10 ]
將鍵對應的值設置為空(nil),就可以刪除這對鍵值。nil是空值,我們將在章節結束的時候更深入的介紹nil。刪除鍵值方法:
homeruns [ "Sandoval" ] = nil // [ "Posey" : 36, "Pagan" : 19, "Pence" : 15 ]
循環(Loops)
想象一下你在健身館運動,你的健身教練告訴你要舉重8次,同樣的舉重動作你要進行8次。編程中處理重復工作使用循環(Loops)。循環用來重復某段特定代碼。
For條件遞增語句(For-Condition-Increment)
最常見的循環就是For條件遞增語句,簡稱for loop(for循環體)。這個循環有三部分構成:一個變量,一個條件,一個遞增。這里的變量常常使用整型,來跟蹤目前的已經完成的循環次數。這里的條件會在每次循環結束之后都會檢查一次,如果條件結果為真,循環繼續,如果條件為假,循環停止。最后,這里的遞增是每次循環執行后需要增加的數值:
for ( var counter = 0; counter < 8; counter++ ) {
liftWeights( )
}
語法是這樣的:用for
作為循環的開始,告訴Xcode你要聲明一個循環了,for后面跟著括號,貨號里面聲明變量、條件和遞增數值。例如:
for ( VARIABLE; CONDITION; INCREMENT ) {
}
括號中的第一個部分是變量,用counter表示,計算已經完成的循環的數量,在平時編寫程序時,這里的變量常常命名為counter(英文中counter有計數器的含義)然后設定初始值為零:
for ( var counter = 0; CONDITION; INCREMENT ) {
}
Page 66 | Chapter3:Diving into Swift
接下來,在變量后面使用分號和條件分隔開來。在這個例子中,條件設定為counter小于8,這將會使循環執行8次。例如:
for ( var counter = 0; counter < 8; INCREMENT ) {
}
條件后面的一個分號后面是遞增值,遞增值就是每次循環后變量counter的變化:
for ( var counter = 0; counter < 8; counter++ ) {
}
大部分的遞增值用兩個加號這種簡寫方式。平時要給一個變量加1,語法一般是這樣的:
counter = counter + 1
這行代碼表示變量counter加上1的值覆蓋counter作為counter的新值,在執行for循環時,counter每次加1。然而蘋果公司提供了簡寫方式,用兩個加號++
表示這個變量加1,例如:
counter++
作用和這個相同:
counter = counter +1
for-in循環
每次寫循環語句都要寫變量、條件和增值,這可是一件費時費力的體力活。而for-in循環提供了一種更簡單的方法去遍歷(循環訪問)一個數組或者詞典。for-in循環可以自動的檢測條件和遞增值。此外,還會提供一個變量來表示目前數組中的元素。例如:
var favoriteStates = ["California", "New York", "Colorado", "Oregon"]
for state in favoriteStates {
println ( "\(state) is one of my favorite states" )
}
//California is one of my favorite states
//New York is one of my favorite states
//Colorado is one of my favorite states
//Oregon is one of my favorite states
println
方法,發音為"print line",能夠生成字符串內容然后將內容展示在Debugger中(也就是常說的“打印”)。Debugger會在第六章中介紹。
Loops | Page67
for-in循環同樣也可以在詞典中使用,遍歷詞典中所有的鍵值,不過需要為鍵值設置2個變量:
var homeruns = [ "Posey" : 24, "Pagan" : 19, "Pence" : 15 ]
for (name, hrs) in homeruns {
println( " \(name) has \(hrs) Homeruns this season.")
}
//Posey has 24 Homeruns this season.
//Pagan has 19 Homeruns this season.
//Pence has 15 Homeruns this season.
區間(Ranges)
區間Range和整型數組中一個數字到另一個數字差不多,目前有兩種區間,一種是閉區間,用三個小點表示,包含小點兩邊的數字:
1...5 //1,2,3,4,5
另外一種是半閉半開區間,用兩個小點加上一個小于號表示,小于號右邊的數字不包含在這個區間中:
1..<5 //1,2,3,4
在for-in循環中,可以使用區間來代替數組或者詞典:
for index in 1...5 {
println ("The current number is \(index)")
}
//The current number is 1
//The current number is 2
//The current number is 3
//The current number is 4
//The current number is 5
條件表達式(Conditional Statements)
你是否在餐館遇到過會給過生日的人唱歌的情景?這就是一個條件表達式,在程序中,條件表達式是用來做決定的。
Page 68 | Chapter3:Diving into Swift
if表達式(if Statements)
類似這種做決定的情況或者可以判斷是和否的邏輯問題,都可以使用條件表達式。if表達式決定一個情況為真或者為假,如果條件為真,某段代碼就會執行,如果為假,則這段代碼不會執行。例如:
if isBirthdayToday == true {
singBirthdaySong ( )
}
條件表達式以if開頭,然后跟著條件,在上面的這個例子中,條件是isBirthdayToday == true
,兩個等號表示比較2個等號之間的數值,如果值相同,則結果為真,如果值不相同,則結果為假。如果為真,就會執行singBirthdaySong ( )
這個方法,如果為假,就會不執行singBirthdaySong ( )
這個方法。最后,兩個大括號表示這段代碼的開始和結尾。
if-else表達式
在歌劇結束后,按慣例演員會出來謝幕,性別不同會有不同的動作,要么鞠躬,要么行屈膝禮。如果你想在Swift中表達這件事,可以這樣寫:
if isMale == true {
bow()
} else {
curtsy()
}
在這里例子中,我們需要看isMale是否為真,如果為真,bow()
將會執行,如果為假,curtsy()
將會執行,上面和下面兩部分是相互排斥的,換句話說,你只能執行其中一個,要么上面,要么下面。
有時候你需要檢查多個情況才能決定下一步做什么。比如你早上起床后,在工作日會有一套例行事宜,而在周末就會有另外一套例行事宜:
if isWeekday == true {
getReadyForWork()
} else if isSaturday == true {
goRunning()
} else {
goToYoga()
}
Conditional Statements | Page69
在這個例子中,你首先要檢查今天是不是工作日,如果今天是工作日,就要執行getReadyForWork()
,然后跳過if語句中剩下的代碼。如果今天不是工作日,就要跳過第一部分然后進入else if條件。
如果第一個條件為假,else if會被調用。如果今天是周六,goRunning()
代碼執行,然后跳過剩下的代碼。
最后,如果上面兩個條件都為假,那么else就會被調用。如果今天既不是工作日也不是周六,那么 goToYoga()
會執行。
在日常的編程中,if條件句是非常有力的工具,經常使用if來控制邏輯。記住,要檢查每個條件,確保結果只有真或假兩種情況。
可選類型(Optionals)
可選值是用來處理那些可能出現空值的變量。在某些情況下,你是無法確保一個變量是不是一定有值。例如,在西班牙語中的一個單詞,可能無法直接翻譯成英語的一個單詞,這樣就會出現空值。這種沒有值的情況叫做nil。
可選值可以用在任何類型的變量中,在使用時將一個問號跟在類型后面,表示這是可選值:
var translatedWord: String?
因為可能為空的變量都必須名稱表示,這樣能確保所有的非可選值變量都會有值。這種設計模式幫助開發者避免了空值引起的程序崩潰。非可選值變量都必須有值,可選值變量可以沒有值。
可選值不能直接使用,在使用之前需要解包(unwrapped)。把使用可選值變量想象成拆開一袋糖果,必須先要把包裝撕掉才能吃到糖果。當一個可選值變量解包后,這個變量也可能是空值。這就相當于你拆開一顆糖果,結果發現里面什么也沒有。
解包的過程幫助開發者記住去檢查然后確保這個變量不是空值,用可選值有2個步驟,第一步,檢查是不是為空,一般情況下用if表達式檢查:
var translatedWord: String? = translate("cat")
if translatedWord != nil {
//translatedWord has a value
} else {
//The translatedWord has no value
}
Page 70 | Chapter3:Diving into Swift
一旦核查確實有值后,你必須解包。解包一個可選值非常簡單,直接放一個嘆號在變量后面即可,例如:
var translatedWord: String? = translate("cat")
if translatedWord != nil {
println(translatedWord!) //gato
}
剛剛開始接觸可選值的時候會有一些困惑和不習慣,其實你只要記住,一個可能為空的變量必須是可選值,而當可選值為空時就叫做nil。
在這一章節,你學會了Swift的基本知識,你現在能夠聲明變量、常量、甚至是可選值了。你熟悉了如何聲明字符串,整型,浮點型,數組和詞典,你也理解了如果聲明一個循環體,一個條件語句。現在,是時候讓你接受一下檢測了,再接再勵完成小費計算器程序吧~