告訴計算機在什么時候該做什么萨惑,稱做控制流捐康。
在本教程中,您將學(xué)習(xí)如何來控制流程庸蔼,從而讓計算機聽你的話解总。您還將了解布爾值true
和false
,以及如何使用它們來比較數(shù)據(jù)姐仅。
入門
此前學(xué)過了一些類型如Int
花枫,Double
和String
。在這里掏膏,您將學(xué)習(xí)另一種類型:布爾劳翰。
如,查找兩個數(shù)字中的較大者馒疹,答案是true或false佳簸。
let yes = true // 類型推斷為Bool
let no = false // 類型推斷為Bool
布爾類型的值只能是true
或false
。
布爾運算符
布爾值通常用于比較值颖变。例如溺蕉,您可能有兩個值,并且您想知道它們是否相等:值是相同的(true)還是它們是不同的(false)悼做。
在Swift中疯特,使用==執(zhí)行此操作:
let doesOneEqualTwo = (1 == 2)
swift推斷doesOneEqualTwo
是一個Bool
。顯然肛走,1不等于2漓雅,因此doesOneEqualTwo
將是false
。
同樣朽色,你可以看看兩個值是否不相等:
let doesOneNotEqualTwo = (1 != 2)
因為1不等于2邻吞,所以doesOneNotEqualTwo
會是true
。
!
叫取反操作葫男。
大于(>
)抱冷,小于(<
):
let isOneGreaterThanTwo = (1 > 2)
let isOneLessThanTwo = (1 < 2)
isOneGreaterThanTwo
為false
,isOneLessThanTwo
為true
梢褐。
另外還有小于等于和大于等于:<=
旺遮,>=
赵讯,同理。
布爾邏輯
且&&
耿眉。如果兩個都是true
边翼,結(jié)果才是true
。否則鸣剪,結(jié)果是false
组底。
let and = true && true
在這種情況下,and
將是true
筐骇。如果右邊的任何一個值是false
债鸡,那么and
就是false
。
或||
铛纬。只要其中一個為true厌均,則結(jié)果為true。
let or = true || false
在這種情況下饺鹃,or
將是true
。如果右邊的兩個值都是false
间雀,那么or
就是false
悔详。如果兩者都是true
,那么or
仍然是true
惹挟。
在Swift中茄螃,布爾邏輯通常應(yīng)用于多個條件:
let andTrue = 1 < 2 && 4 > 3
let andFalse = 1 < 2 && 3 > 4
let orTrue = 1 < 2 || 3 > 4
let orFalse = 1 == 2 || 3 == 4
也可以這樣:
let andOr = (1 < 2 && 3 > 4) || 1 < 4
字符串比較
在Swift,用于比較數(shù)字是否相等的==
號也可以用來比較字符串:
let guess = "dog"
let dogEqualsCat = guess == "cat"
得出dogEqualsCat
是一個布爾類型连锯,為false
归苍。
與數(shù)字一樣,您不僅可以比較是否相等运怖,還可以比較一個值是否大于或小于另一個值:
let order = "cat" < "dog"
這時是按英文字母順序比較拼弃,order
為true
if語句
流程控制的第一個也是最常見的是if
,只有當(dāng)某個條件為true
時才執(zhí)行:
if 2 > 1 {
print("Yes, 2 is greater than 1.")
}
這是一個簡單的if
語句摇展。如果條件是true
吻氧,則將執(zhí)行大括號之間的代碼。如果條件為false
咏连,則語句將不執(zhí)行大括號之間的代碼盯孙。
您可以擴展if
語句:
let animal = "Fox"
if animal == "Cat" || animal == "Dog" {
print("Animal is a house pet.")
} else {
print("Animal is not a house pet.")
}
這里,如果animal
等于"Cat"
或者"Dog"
祟滴,那么語句將運行第一個代碼塊振惰。如果animal
不等于"Cat"
或者"Dog"
,則將在else
內(nèi)運行垄懂,以下內(nèi)容被打印到控制臺:
Animal is not a house pet.
else if
:
let hourOfDay = 12
var timeOfDay = ""
if hourOfDay < 6 {
timeOfDay = "Early morning"
} else if hourOfDay < 12 {
timeOfDay = "Morning"
} else if hourOfDay < 17 {
timeOfDay = "Afternoon"
} else if hourOfDay < 20 {
timeOfDay = "Evening"
} else if hourOfDay < 24 {
timeOfDay = "Late evening"
} else {
timeOfDay = "INVALID HOUR!"
}
print(timeOfDay)
if
語句將逐個測試多個條件骑晶,直到true
痛垛。無論后面的else-if
條件是否為true,僅執(zhí)行第一條true
后面的代碼透罢。
末尾的else
子句來處理以上都為false
的情況榜晦。
控制臺將打印出以下內(nèi)容:
Afternoon
封裝變量
if
語句引入了一個新的概念范圍,這是一種通過使用大括號封裝變量的方法羽圃。
如乾胶,某地兼職工資的規(guī)定為:在40小時之前每小時25美元,之后每小時50美元朽寞。
通過以下方式計算您的工資:
var hoursWorked = 45
var price = 0
if hoursWorked > 40 {
let hoursOver40 = hoursWorked - 40
price += hoursOver40 * 50
hoursWorked -= hoursOver40
}
price += hoursWorked * 25
print(price)
結(jié)果如下:
1250
hoursOver40
是在if
語句中聲明的新常量识窿。如果這樣會發(fā)生什么?
// ...
print(price)
print(hoursOver40)
這將導(dǎo)致以下錯誤:
Use of unresolved identifier 'hoursOver40'
此錯誤通知您脑融,您只能在創(chuàng)建它的范圍內(nèi)使用hoursOver40
常量喻频。在這種情況下,if
語句創(chuàng)建了一個新范圍肘迎,因此當(dāng)該范圍結(jié)束后甥温,您將無法使用該常量。
但是妓布,每個范圍都可以使用其父范圍中的變量和常量姻蚓。在上面的示例中,if
語句內(nèi)部仍然可以使用您在父范圍中創(chuàng)建的price
和hoursWorked
變量匣沼。
三元運算
三元運算符即返回兩個值中的一個狰挡,這取決于條件是true
還是false
:
(<CONDITION>) ? <TRUE VALUE> : <FALSE VALUE>
這是一個找出兩個變量中最小值的示例:
let a = 5
let b = 10
let min: Int
if a < b {
min = a
} else {
min = b
}
感謝三元運算符,您可以重寫為簡潔的代碼:
let a = 5
let b = 10
let min = a < b ? a : b
如果a < b
是true
释涛,則min
的值為a
;如果是false
加叁,min
為b
。
注意:如果過度使用唇撬,可能會犧牲代碼的易讀性它匕。
循環(huán)
循環(huán)是多次執(zhí)行代碼的一種方式。在本節(jié)中窖认,您將了解while
循環(huán)超凳。
循環(huán)時
當(dāng)while
后面條件為true
時,將循環(huán)執(zhí)行大括號中的代碼:
while <CONDITION> {
<LOOP CODE>
}
每一次循環(huán)耀态,都會先檢查條件轮傍。如果條件是true
,則執(zhí)行并準(zhǔn)備下一次循環(huán)首装。一旦條件為false
创夜,則循環(huán)停止。就像if
語句一樣仙逻,while
循環(huán)也引入了一個范圍(大括號中的代碼)驰吓。
最簡單的while
循環(huán):
while true {
}
這是一個永遠(yuǎn)不會結(jié)束的while
循環(huán)(死循環(huán))涧尿,因為條件總是true
。一個死循環(huán)可能不會讓程序崩潰檬贰,但很可能會讓計算機死機姑廉。
一個while
循環(huán)示例:
var sum = 1
while sum < 1000 {
sum = sum + (sum + 1)
}
此代碼計算一個數(shù)學(xué)序列,直到sum
值大于1000
翁涤。
循環(huán)執(zhí)行如下:
在第九次迭代(循環(huán))之后铁蹈,sum
是1023
千元,循環(huán)條件sum < 1000
變?yōu)?code>false,循環(huán)停止。
repeat-while循環(huán)
它與while
循環(huán)的不同之處在于习蓬,在循環(huán)結(jié)束時判斷條件是否為true
:
repeat {
<LOOP CODE>
} while <CONDITION>
這是上一節(jié)的示例级零,使用repeat-while
循環(huán):
sum = 1
repeat {
sum = sum + (sum + 1)
} while sum < 1000
在此示例中富纸,結(jié)果和之前相同集畅。但并非所有的時候都是一樣的。
while
循環(huán):
sum = 1
while sum < 1 {
sum = sum + (sum + 1)
}
repeat-while
循環(huán):
sum = 1
repeat {
sum = sum + (sum + 1)
}while sum < 1
在while
循環(huán)中届谈,條件從一開始就是false
枯夜。說明不會執(zhí)行循環(huán)體,sum
最終為1
艰山。
在repeat-while
中湖雹,sum
為3
,因為循環(huán)體將先執(zhí)行一次程剥。
跳出循環(huán)
有時你想早點結(jié)束循環(huán)劝枣√捞ぃ可以使用break
語句织鲸,該語句會立即停止循環(huán)并繼續(xù)循環(huán)后面的代碼:
sum = 1
while true {
sum = sum + (sum + 1)
if sum >= 1000 {
break
}
}
條件為true
,所以會永遠(yuǎn)循環(huán)溪胶。但一旦sum
大于或等于1000
搂擦,循環(huán)將結(jié)束。
高級控制流
在本節(jié)中哗脖,您將繼續(xù)學(xué)習(xí)如何控制代碼執(zhí)行瀑踢。您將了解另一個稱為for
循環(huán)的循環(huán)。
范圍
在深入了解for
循環(huán)語句之前才避,您需要了解一下ClosedRange
和Range
類型橱夭,它們可以表示一系列的數(shù)字。
封閉的范圍:
let closedRange = 0...5
三個點(...
)表示范圍是從0到5(包括0和5)桑逝。即0, 1, 2, 3, 4, 5
棘劣。
半開放范圍:
let halfOpenRange = 0..<5
范圍是從0到5,包括0但不包括5楞遏。即0, 1, 2, 3, 4
茬暇。
注意:
第二個數(shù)字必須始終大于或等于第一個數(shù)字首昔。
范圍通常用于for
循環(huán)和switch
語句中!
for循環(huán)
for <CONSTANT> in <RANGE> {
<LOOP CODE>
}
循環(huán)以for
關(guān)鍵字開頭糙俗,后面跟一個想在循環(huán)中使用的常量名勒奇,in
后面為循環(huán)的范圍:
let count = 10
var sum = 0
for i in 1...count {
sum += i
}
i
的初始值為1,也就是范圍(1...count
)的第一個數(shù)巧骚,每次循環(huán)之后都加1赊颠,直到等于count
為止。
以下是每次迭代的i
和sum
的值:
i
循環(huán)外部不可用网缝。
當(dāng)你在循環(huán)中不需要使用i
時巨税,可以用下劃線:
sum = 1
var lastSum = 0
for _ in 0..<count {
let temp = sum
sum = sum + lastSum
lastSum = temp
}
只是單純的想讓代碼執(zhí)行一定的次數(shù),不需要用到循環(huán)常量(上述i
)粉臊。
0..<count
半開草添,表示代碼將執(zhí)行count
次,這是一種需要執(zhí)行多少次的常用方法扼仲。
也可以僅在某些條件下執(zhí)行循環(huán)远寸。如,想要計算總和但僅針對奇數(shù):
var sum = 0
for i in 1...count where i % 2 == 1 {
sum += i
}
where
為for
循環(huán)中的一個子句屠凶。循環(huán)只會在where
條件為true
時執(zhí)行循環(huán)體驰后。
continue聲明
有時你想跳過特定情況的循環(huán)迭代,而不想完全跳出循環(huán)矗愧≡钪ィ可以使用continue
語句,該語句立即結(jié)束循環(huán)的當(dāng)前迭代并開始下一次迭代唉韭。
8?8乘法表:
假設(shè)您想要計算所有單元格的總和但排除所有偶數(shù)行:
使用for
循環(huán):
sum = 0
for row in 0..<8 {
if row % 2 == 0 {
continue
}
for column in 0..<8 {
sum += row * column
}
}
模2為0時夜涕,該行是偶數(shù)行。在這種情況下属愤,continue
跳出本次for
循環(huán)女器,執(zhí)行下一次循環(huán)。
和break
一樣住诸,continue
也適用于for
循環(huán)和while
循環(huán)驾胆。
switch語句
控制流的另一種是switch
語句,它允許您根據(jù)變量或常量的值執(zhí)行不同的代碼贱呐。
一個非常簡單的switch
語句:
let number = 10
switch number {
case 0:
print("Zero")
default:
print("Non-zero")
}
將輸出:
Non-zero
case
后面的值(本例中為0
)表示:當(dāng)number
為此值時丧诺,執(zhí)行冒號后面的語句。default
表示以上全沒有匹配到的話執(zhí)行下面的代碼奄薇。
另一個例子:
switch number {
case 10:
print("It's ten!")
default:
break
}
這次匹配到10驳阎,將執(zhí)行case下面的代碼。
break
表示什么都不執(zhí)行,
switch
語句適用于任何數(shù)據(jù)類型搞隐!以下是切換字符串的示例:
let string = "Dog"
switch string {
case "Cat", "Dog":
print("Animal is a house pet.")
default:
print("Animal is not a house pet.")
}
這將打印以下內(nèi)容:
Animal is a house pet.
case
后接兩個值驹愚,這說明如果等于"Cat"
或者"Dog"
將執(zhí)行。
高級switch語句
case
后接多種情況:
let hourOfDay = 12
var timeOfDay = ""
switch hourOfDay {
case 0, 1, 2, 3, 4, 5:
timeOfDay = "Early morning"
case 6, 7, 8, 9, 10, 11:
timeOfDay = "Morning"
case 12, 13, 14, 15, 16:
timeOfDay = "Afternoon"
case 17, 18, 19:
timeOfDay = "Evening"
case 20, 21, 22, 23:
timeOfDay = "Late evening"
default:
timeOfDay = "INVALID HOUR!"
}
print(timeOfDay)
將輸出以下內(nèi)容:
Afternoon
可以使用范圍讓代碼更簡潔:
var timeOfDay2 = ""
switch hourOfDay {
case 0...5:
timeOfDay2 = "Early morning"
case 6...11:
timeOfDay2 = "Morning"
case 12...16:
timeOfDay2 = "Afternoon"
case 17...19:
timeOfDay2 = "Evening"
case 20..<24:
timeOfDay2 = "Late evening"
default:
timeOfDay2 = "INVALID HOUR!"
}
print(timeOfDay2)
也可以像for循環(huán)一樣使用where
子句(先聲明一個常量以便where子句中使用):
switch number {
case let x where x % 2 == 0:
print("Even")
default:
print("Odd")
}
這將打印以下內(nèi)容:
Even
如for循環(huán)一樣劣纲,聲明的常量在下面的代碼中不需要使用的話逢捺,可以用下劃線代替:
switch number {
case _ where number % 2 == 0:
print("Even")
default:
print("Odd")
}
部分匹配
let coordinates = (x: 3, y: 2, z: 5)
switch coordinates {
case (0, 0, 0): // 1
print("Origin")
case (_, 0, 0): // 2
print("On the x-axis.")
case (0, _, 0): // 3
print("On the y-axis.")
case (0, 0, _): // 4
print("On the z-axis.")
default: // 5
print("Somewhere in space")
}
該switch
語句使用部分匹配:
- 精確匹配
(0, 0, 0)
。說明時3D空間的原點癞季。 - 匹配y = 0劫瞳,z = 0和x可為任何值。說明坐標(biāo)位于x軸上绷柒。
- 匹配x = 0志于,z = 0和y可為任何值。說明坐標(biāo)位于y軸上废睦。
- 匹配x = 0伺绽,y = 0和z可為任何值。說明坐標(biāo)位于z軸上嗜湃。
- 匹配其余坐標(biāo)奈应。
把上例中的下劃線聲明為變量,這樣可以在case后面的語句中使用:
switch coordinates {
case (0, 0, 0):
print("Origin")
case (let x, 0, 0):
print("On the x-axis at x = \(x)")
case (0, let y, 0):
print("On the y-axis at y = \(y)")
case (0, 0, let z):
print("On the z-axis at z = \(z)")
case let (x, y, z):
print("Somewhere in space at x = \(x), y = \(y), z = \(z)")
}
使用let
語法來提取相關(guān)值购披。然后使用字符串插值打印出來杖挣。
此switch
語句中沒有default
選項。因為已經(jīng)窮舉了所有情況刚陡,所以不用寫默認(rèn)值惩妇。
注:想提取元組的所有值時,let (x, y, z)
和(let x, let y, let z)
一樣筐乳。
最后歌殃,可以使用let-where
語法來匹配更復(fù)雜的情況:
switch coordinates {
case let (x, y, _) where y == x:
print("Along the y = x line.")
case let (x, y, _) where y == x * x:
print("Along the y = x^2 line.")
default:
break
}