1. For in 循環(huán)
遍歷一個(gè)集合中的所有元素匀们。 例如:數(shù)組中的元素惭载、范圍內(nèi)的數(shù)字或者字符串中的字符旱函。
- 遍歷一個(gè)數(shù)組所有元素:
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
print("Hello, \(name)!")
}
// Hello, Anna!
// Hello, Alex!
// Hello, Brian!
// Hello, Jack!
- 遍歷一個(gè)字典來(lái)訪問(wèn)它的鍵值對(duì):
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
print("\(animalName)s have \(legCount) legs")
}
// cats have 4 legs
// ants have 6 legs
// spiders have 8 legs
- 遍歷數(shù)字范圍
for index in 1...5 {
print("\(index) times 5 is \(index * 5)")
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25
- 不需要區(qū)間序列內(nèi)一項(xiàng)的值,你可以使用下劃線(_)替代變量名來(lái)忽略這個(gè)值:
let base = 3
let power = 10
var answer = 1
for _ in 1...power {
answer *= base
}
print("\(base) to the power of \(power) is \(answer)") // 輸出“3 to the power of 10 is 59049”
- 使用半開(kāi)區(qū)間運(yùn)算符(..<)來(lái)表示一個(gè)左閉右開(kāi)的區(qū)間:
let minutes = 60
for tickMark in 0..<minutes {
// 每一分鐘都渲染一個(gè)刻度線(60次)
}
- 可以每 5 分鐘作為一個(gè)刻度描滔。使用 stride(from:to:by:) 函數(shù)跳過(guò)不需要的標(biāo)記:
let minuteInterval = 5
let minutes = 60
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
// 每5分鐘渲染一個(gè)刻度線(0, 5, 10, 15 ... 45, 50, 55)
}
- 在閉區(qū)間使用 stride(from:through:by:) 起到同樣作用:
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
// 每3小時(shí)渲染一個(gè)刻度線(3, 6, 9, 12)
}
2. While 循環(huán)
while 循環(huán)會(huì)一直運(yùn)行一段語(yǔ)句直到條件變成 false棒妨。Swift 提供兩種 while 循環(huán)形式:
- while 循環(huán),每次在循環(huán)開(kāi)始時(shí)計(jì)算條件是否符合。
- repeat-while 循環(huán)券腔,每次在循環(huán)結(jié)束時(shí)計(jì)算條件是否符合伏穆。
2.1 While
- while 循環(huán)從計(jì)算一個(gè)條件開(kāi)始。如果條件為 true纷纫,會(huì)重復(fù)運(yùn)行一段語(yǔ)句枕扫,直到條件變?yōu)?false。
- while 循環(huán)的一般格式:
while condition {
statements
}
2.2 Repeat-While
- 判斷循環(huán)條件之前辱魁,先執(zhí)行一次循環(huán)的代碼塊烟瞧。然后重復(fù)循環(huán)直到條件為 false。
- repeat-while 循環(huán)的一般格式:
repeat {
statements
} while condition
3. 條件語(yǔ)句
3.1 if
- 該條件為 true 時(shí)染簇,才執(zhí)行相關(guān)代碼:
temperatureInFahrenheit = 40
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
} else {
print("It's not that cold. Wear a t-shirt.")
} // 輸出“It's not that cold. Wear a t-shirt.”
- 可以把多個(gè) if 語(yǔ)句鏈接在一起参滴,來(lái)實(shí)現(xiàn)更多分支:
temperatureInFahrenheit = 90
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
print("It's really warm. Don't forget to wear sunscreen.")
} else {
print("It's not that cold. Wear a t-shirt.")
} // 輸出“It's really warm. Don't forget to wear sunscreen.”
- 不需要完整判斷情況的時(shí)候,最后的 else 語(yǔ)句是可選的:
temperatureInFahrenheit = 72
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
print("It's really warm. Don't forget to wear sunscreen.")
}
3.2 Switch
switch 語(yǔ)句會(huì)嘗試把某個(gè)值與若干個(gè)模式(pattern)進(jìn)行匹配锻弓。
3.2.1 不存在隱式的貫穿
與 C 和 Objective-C 中的 switch 語(yǔ)句不同砾赔,在 Swift 中,當(dāng)匹配的 case 分支中的代碼執(zhí)行完畢后青灼,程序會(huì)終止 switch 語(yǔ)句暴心,而不會(huì)繼續(xù)執(zhí)行下一個(gè) case 分支。
- 把某個(gè)值與一個(gè)或若干個(gè)相同類型的值作比較:
let someCharacter: Character = "z"
switch someCharacter {
case "a":
print("The first letter of the alphabet")
case "z":
print("The last letter of the alphabet")
default:
print("Some other character")
} // 輸出“The last letter of the alphabet”
- Swift 中 break 不是必須的聚至。
- 在 Swift 中酷勺,當(dāng)匹配的 case 分支中的代碼執(zhí)行完畢后,程序會(huì)終止 switch 語(yǔ)句扳躬,而不會(huì)繼續(xù)執(zhí)行下一個(gè) case 分支脆诉。這也就是說(shuō),不需要在 case 分支中顯式地使用 break 語(yǔ)句贷币。
- 每一個(gè) case 分支都必須包含至少一條語(yǔ)句:
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a": // 無(wú)效击胜,這個(gè)分支下面沒(méi)有語(yǔ)句
case "A":
print("The letter A")
default:
print("Not the letter A")
}
!R畚啤偶摔!這段代碼會(huì)報(bào)編譯錯(cuò)誤
- 讓單個(gè) case 同時(shí)匹配 a 和 A,可以將這個(gè)兩個(gè)值組合成一個(gè)復(fù)合匹配促脉,并且用逗號(hào)分開(kāi):
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A":
print("The letter A")
default:
print("Not the letter A")
} // 輸出“The letter A”
3.2.2 區(qū)間匹配
- case 分支的模式也可以是一個(gè)值的區(qū)間
let approximateCount = 62
let countedThings = "moons orbiting Saturn"
let naturalCount: String
switch approximateCount {
case 0:
naturalCount = "no"
case 1..<5:
naturalCount = "a few"
case 5..<12:
naturalCount = "several"
case 12..<100:
naturalCount = "dozens of"
case 100..<1000:
naturalCount = "hundreds of"
default:
naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).") // 輸出“There are dozens of moons orbiting Saturn.”
3.2.3 元組匹配
- 可以使用元組在同一個(gè) switch 語(yǔ)句中測(cè)試多個(gè)值辰斋。
- 元組中的元素可以是值,也可以是區(qū)間瘸味。
- 使用下劃線(_)來(lái)匹配所有可能的值宫仗。
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
print("\(somePoint) is at the origin")
case (_, 0):
print("\(somePoint) is on the x-axis")
case (0, _):
print("\(somePoint) is on the y-axis")
case (-2...2, -2...2):
print("\(somePoint) is inside the box")
default:
print("\(somePoint) is outside of the box")
} // 輸出“(1, 1) is inside the box”
Swift 允許多個(gè) case 匹配同一個(gè)值。
在這個(gè)例子中旁仿,點(diǎn) (0, 0)可以匹配所有四個(gè) case藕夫。
如果存在多個(gè)匹配,那么只會(huì)執(zhí)行第一個(gè)被匹配到的 case 分支。
點(diǎn) (0, 0)會(huì)首先匹配 case (0, 0)毅贮,因此剩下的能夠匹配的分支都會(huì)被忽視掉办悟。
3.2.4 值綁定(Value Bindings)
case 分支允許將匹配的值聲明為臨時(shí)常量或變量,并且在 case 分支體內(nèi)使用 —— 這種行為被稱為值綁定(value binding)滩褥,因?yàn)槠ヅ涞闹翟?case 分支體內(nèi)病蛉,與臨時(shí)的常量或變量綁定。
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("on the x-axis with an x value of \(x)")
case (0, let y):
print("on the y-axis with a y value of \(y)")
case let (x, y):
print("somewhere else at (\(x), \(y))")
} // 輸出“on the x-axis with an x value of 2”
注意:
這個(gè) switch 語(yǔ)句不包含默認(rèn)分支铸题。這是因?yàn)樽詈笠粋€(gè) case ——case let(x, y) 聲明了一個(gè)可以匹配余下所有值的元組铡恕。這使得 switch 語(yǔ)句已經(jīng)完備了,因此不需要再書(shū)寫(xiě)默認(rèn)分支丢间。
3.2.5 Where
case 分支的模式可以使用 where 語(yǔ)句來(lái)判斷額外的條件探熔。
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
print("(\(x), \(y)) is just some arbitrary point")
} // 輸出“(1, -1) is on the line x == -y”
3.2.6 復(fù)合型 Cases
- 當(dāng)多個(gè)條件可以使用同一種方法來(lái)處理時(shí),可以將這幾種可能放在同一個(gè) case 后面烘挫,并且用逗號(hào)隔開(kāi)诀艰。當(dāng) case 后面的任意一種模式匹配的時(shí)候,這條分支就會(huì)被匹配饮六。并且其垄,如果匹配列表過(guò)長(zhǎng),還可以分行書(shū)寫(xiě):
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
print("\(someCharacter) is a consonant")
default:
print("\(someCharacter) is not a vowel or a consonant")
} // 輸出“e is a vowel”
- 復(fù)合匹配同樣可以包含值綁定卤橄。復(fù)合匹配里所有的匹配模式绿满,都必須包含相同的值綁定。并且每一個(gè)綁定都必須獲取到相同類型的值窟扑。 這保證了喇颁,無(wú)論復(fù)合匹配中的哪個(gè)模式發(fā)生了匹配,分支體內(nèi)的代碼嚎货,都能獲取到綁定的值橘霎,并且綁定的值都有一樣的類型。
let stillAnotherPoint = (9, 0)
switch stillAnotherPoint {
case (let distance, 0), (0, let distance):
print("On an axis, \(distance) from the origin")
default:
print("Not on an axis")
} // 輸出“On an axis, 9 from the origin”
上面的 case 有兩個(gè)模式:
- (let distance, 0) 匹配了在 x 軸上的值殖属,
- (0, let distance) 匹配了在 y 軸上的值姐叁。
兩個(gè)模式都綁定了 distance,并且 distance 在兩種模式下洗显,都是整型——這意味著分支體內(nèi)的代碼外潜,只要 case 匹配,都可以獲取到 distance 值挠唆。
4. 控制轉(zhuǎn)移語(yǔ)句
控制轉(zhuǎn)移語(yǔ)句改變你代碼的執(zhí)行順序橡卤,通過(guò)它可以實(shí)現(xiàn)代碼的跳轉(zhuǎn)。
4.1Swift 有五種控制轉(zhuǎn)移語(yǔ)句:
- continue:告訴一個(gè)循環(huán)體立刻停止本次循環(huán)损搬,重新開(kāi)始下次循環(huán)。
- break:break 語(yǔ)句會(huì)立刻結(jié)束整個(gè)控制流的執(zhí)行。break 可以在 switch 或循環(huán)語(yǔ)句中使用巧勤,用來(lái)提前結(jié)束 switch 或循環(huán)語(yǔ)句嵌灰。
- fallthrough:貫穿(Fallthrough)從上一個(gè) case 分支跳轉(zhuǎn)到下一個(gè) case 分支中。
- return:返回
- throw:錯(cuò)誤拋出
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += " a prime number, and also"
fallthrough
default:
description += " an integer."
}
print(description) // 輸出“The number 5 is a prime number, and also an integer.”
4.2 帶標(biāo)簽的語(yǔ)句
標(biāo)簽(statement label):標(biāo)記一個(gè)循環(huán)體或者條件語(yǔ)句颅悉。
- 對(duì)于一個(gè)條件語(yǔ)句沽瞭,你可以使用 break 加標(biāo)簽的方式,來(lái)結(jié)束這個(gè)被標(biāo)記的語(yǔ)句剩瓶。
- 對(duì)于一個(gè)循環(huán)語(yǔ)句驹溃,你可以使用 break 或者 continue 加標(biāo)簽,來(lái)結(jié)束或者繼續(xù)這條被標(biāo)記語(yǔ)句的執(zhí)行延曙。
- 針對(duì) while 循環(huán)體的標(biāo)簽語(yǔ)法豌鹤,同樣的規(guī)則適用于所有的循環(huán)體和條件語(yǔ)句:
label name: while condition {
statements
}
4.3 提前退出
- 使用 guard 語(yǔ)句來(lái)要求條件必須為真時(shí),以執(zhí)行 guard 語(yǔ)句后的代碼枝缔。
- 不同于 if 語(yǔ)句布疙,一個(gè) guard 語(yǔ)句總是有一個(gè) else 從句,如果條件不為真則執(zhí)行 else 從句中的代碼愿卸。
func greet(person: [String: String]) {
guard let name = person["name"] else {
return
}
?
print("Hello \(name)!")
?
guard let location = person["location"] else {
print("I hope the weather is nice near you.")
return
}
?
print("I hope the weather is nice in \(location).")
}
?
greet(person: ["name": "John"])
// 輸出“Hello John!”
// 輸出“I hope the weather is nice near you.”
greet(person: ["name": "Jane", "location": "Cupertino"])
// 輸出“Hello Jane!”
// 輸出“I hope the weather is nice in Cupertino.”
注意:
1.如果條件不被滿足灵临,在 else 分支上的代碼就會(huì)被執(zhí)行。
2.這個(gè)分支必須轉(zhuǎn)移控制以退出 guard 語(yǔ)句出現(xiàn)的代碼段趴荸。
3.可以用控制轉(zhuǎn)移語(yǔ)句如 return儒溉、break、continue 或者 throw 做這件事发钝,或者調(diào)用一個(gè)不返回的方法或函數(shù)顿涣,例如 fatalError()。
相比于可以實(shí)現(xiàn)同樣功能的 if 語(yǔ)句笼平,按需使用 guard 語(yǔ)句會(huì)提升我們代碼的可讀性园骆。它可以使你的代碼連貫的被執(zhí)行而不需要將它包在 else 塊中,它可以使你在緊鄰條件判斷的地方寓调,處理違規(guī)的情況锌唾。
4.4 檢測(cè) API 可用性
- Swift 內(nèi)置支持檢查 API 可用性,這可以確保我們不會(huì)在當(dāng)前部署機(jī)器上夺英,不小心地使用了不可用的 API晌涕。
- 編譯器使用 SDK 中的可用信息來(lái)驗(yàn)證我們的代碼中使用的所有 API 在項(xiàng)目指定的部署目標(biāo)上是否可用。如果我們嘗試使用一個(gè)不可用的 API痛悯,Swift 會(huì)在編譯時(shí)報(bào)錯(cuò)余黎。
if #available(iOS 10, macOS 10.12, *) {
// 在 iOS 使用 iOS 10 的 API, 在 macOS 使用 macOS 10.12 的 API
} else {
// 使用先前版本的 iOS 和 macOS 的 API
}
- 平臺(tái)名字可以是:iOS,macOS载萌,watchOS 和 tvOS
if #available(平臺(tái)名稱 版本號(hào), ..., *) {
APIs 可用惧财,語(yǔ)句將執(zhí)行
} else {
APIs 不可用巡扇,語(yǔ)句將不執(zhí)行
}